diff --git a/Jenkinsfile b/Jenkinsfile index a8cc1f2..7fc13af 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -125,35 +125,87 @@ pipeline { } } } - stage('Test') { + stage('Test Sqlite') { + environment { + COMPOSE_PROJECT_NAME = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}_sqlite" + COMPOSE_FILE = 'docker/docker-compose.ci.yml' + } when { not { equals expected: 'UNSTABLE', actual: currentBuild.result } } steps { - // Docker image check - /* - sh '''docker run --rm \ - -v /var/run/docker.sock:/var/run/docker.sock \ - -v "$(pwd)/docker:/app" \ - -e CI=true \ - wagoodman/dive:latest --ci-config /app/.dive-ci \ - "${IMAGE}:${BRANCH_LOWER}-ci-${BUILD_NUMBER}" - ''' - */ + sh 'rm -rf ./test/results/junit/*' sh './scripts/ci/fulltest-cypress' } post { always { // Dumps to analyze later - sh 'mkdir -p debug' - sh 'docker logs $(docker-compose ps --all -q fullstack) > debug/docker_fullstack.log 2>&1' - sh 'docker logs $(docker-compose ps --all -q stepca) > debug/docker_stepca.log 2>&1' - sh 'docker logs $(docker-compose ps --all -q pdns) > debug/docker_pdns.log 2>&1' - sh 'docker logs $(docker-compose ps --all -q pdns-db) > debug/docker_pdns-db.log 2>&1' - sh 'docker logs $(docker-compose ps --all -q dnsrouter) > debug/docker_dnsrouter.log 2>&1' + sh 'mkdir -p debug/sqlite' + sh 'docker logs $(docker-compose ps --all -q fullstack) > debug/sqlite/docker_fullstack.log 2>&1' + sh 'docker logs $(docker-compose ps --all -q stepca) > debug/sqlite/docker_stepca.log 2>&1' + sh 'docker logs $(docker-compose ps --all -q pdns) > debug/sqlite/docker_pdns.log 2>&1' + sh 'docker logs $(docker-compose ps --all -q pdns-db) > debug/sqlite/docker_pdns-db.log 2>&1' + sh 'docker logs $(docker-compose ps --all -q dnsrouter) > debug/sqlite/docker_dnsrouter.log 2>&1' junit 'test/results/junit/*' + sh 'docker-compose down --rmi all --remove-orphans --volumes -t 30 || true' + } + } + } + stage('Test Mysql') { + environment { + COMPOSE_PROJECT_NAME = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}_mysql" + COMPOSE_FILE = 'docker/docker-compose.ci.mysql.yml' + } + when { + not { + equals expected: 'UNSTABLE', actual: currentBuild.result + } + } + steps { + sh 'rm -rf ./test/results/junit/*' + sh './scripts/ci/fulltest-cypress' + } + post { + always { + // Dumps to analyze later + sh 'mkdir -p debug/mysql' + sh 'docker logs $(docker-compose ps --all -q fullstack) > debug/mysql/docker_fullstack.log 2>&1' + sh 'docker logs $(docker-compose ps --all -q stepca) > debug/mysql/docker_stepca.log 2>&1' + sh 'docker logs $(docker-compose ps --all -q pdns) > debug/mysql/docker_pdns.log 2>&1' + sh 'docker logs $(docker-compose ps --all -q pdns-db) > debug/mysql/docker_pdns-db.log 2>&1' + sh 'docker logs $(docker-compose ps --all -q dnsrouter) > debug/mysql/docker_dnsrouter.log 2>&1' + junit 'test/results/junit/*' + sh 'docker-compose down --rmi all --remove-orphans --volumes -t 30 || true' + } + } + } + stage('Test Postgres') { + environment { + COMPOSE_PROJECT_NAME = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}_postgres" + COMPOSE_FILE = 'docker/docker-compose.ci.postgres.yml' + } + when { + not { + equals expected: 'UNSTABLE', actual: currentBuild.result + } + } + steps { + sh 'rm -rf ./test/results/junit/*' + sh './scripts/ci/fulltest-cypress' + } + post { + always { + // Dumps to analyze later + sh 'mkdir -p debug/postgres' + sh 'docker logs $(docker-compose ps --all -q fullstack) > debug/postgres/docker_fullstack.log 2>&1' + sh 'docker logs $(docker-compose ps --all -q stepca) > debug/postgres/docker_stepca.log 2>&1' + sh 'docker logs $(docker-compose ps --all -q pdns) > debug/postgres/docker_pdns.log 2>&1' + sh 'docker logs $(docker-compose ps --all -q pdns-db) > debug/postgres/docker_pdns-db.log 2>&1' + sh 'docker logs $(docker-compose ps --all -q dnsrouter) > debug/postgres/docker_dnsrouter.log 2>&1' + junit 'test/results/junit/*' + sh 'docker-compose down --rmi all --remove-orphans --volumes -t 30 || true' } } } @@ -226,7 +278,6 @@ pipeline { } post { always { - sh 'docker-compose down --rmi all --remove-orphans --volumes -t 30 || true' sh './scripts/ci/build-cleanup' echo 'Reverting ownership' sh 'docker run --rm -v $(pwd):/data jc21/gotools:latest chown -R "$(id -u):$(id -g)" /data' diff --git a/backend/cmd/server/main.go b/backend/cmd/server/main.go index ad64bfe..76c95a8 100644 --- a/backend/cmd/server/main.go +++ b/backend/cmd/server/main.go @@ -69,8 +69,8 @@ func checkSetup() { if db != nil { db.Model(&user.Model{}). - Where("is_disabled = ?", false). - Where("is_system = ?", false). + Where("is_disabled = ?", 0). + Where("is_system = ?", 0). Count(&count) if count == 0 { diff --git a/backend/embed/migrations/mysql/20201013035318_initial_schema.sql b/backend/embed/migrations/mysql/20201013035318_initial_schema.sql new file mode 100644 index 0000000..6573fa7 --- /dev/null +++ b/backend/embed/migrations/mysql/20201013035318_initial_schema.sql @@ -0,0 +1,246 @@ +-- migrate:up + +CREATE TABLE IF NOT EXISTS `jwt_keys` +( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `created_at` BIGINT NOT NULL DEFAULT 0, + `updated_at` BIGINT NOT NULL DEFAULT 0, + `is_deleted` INT NOT NULL DEFAULT 0, + `public_key` TEXT NOT NULL, + `private_key` TEXT NOT NULL +); + +CREATE TABLE IF NOT EXISTS `user` +( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `created_at` BIGINT NOT NULL DEFAULT 0, + `updated_at` BIGINT NOT NULL DEFAULT 0, + `is_deleted` INT NOT NULL DEFAULT 0, + `name` VARCHAR(50) NOT NULL, + `nickname` VARCHAR(50) NOT NULL, + `email` VARCHAR(255) NOT NULL, + `is_system` INT NOT NULL DEFAULT 0, + `is_disabled` INT NOT NULL DEFAULT 0 +); + +CREATE TABLE IF NOT EXISTS `capability` +( + `name` VARCHAR(50) PRIMARY KEY, + UNIQUE (`name`) +); + +CREATE TABLE IF NOT EXISTS `user_has_capability` +( + `user_id` INT NOT NULL, + `capability_name` VARCHAR(50) NOT NULL, + UNIQUE (`user_id`, `capability_name`), + FOREIGN KEY (`capability_name`) REFERENCES `capability`(`name`) +); + +CREATE TABLE IF NOT EXISTS `auth` +( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `created_at` BIGINT NOT NULL DEFAULT 0, + `updated_at` BIGINT NOT NULL DEFAULT 0, + `is_deleted` INT NOT NULL DEFAULT 0, + `user_id` INT NOT NULL, + `type` VARCHAR(50) NOT NULL, + `secret` VARCHAR(255) NOT NULL, + FOREIGN KEY (`user_id`) REFERENCES `user`(`id`), + UNIQUE (`user_id`, `type`) +); + +CREATE TABLE IF NOT EXISTS `setting` +( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `created_at` BIGINT NOT NULL DEFAULT 0, + `updated_at` BIGINT NOT NULL DEFAULT 0, + `is_deleted` INT NOT NULL DEFAULT 0, + `name` VARCHAR(50) NOT NULL, + `description` VARCHAR(255) NOT NULL DEFAULT '', + `value` TEXT NOT NULL, + UNIQUE (`name`) +); + +CREATE TABLE IF NOT EXISTS `audit_log` +( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `created_at` BIGINT NOT NULL DEFAULT 0, + `updated_at` BIGINT NOT NULL DEFAULT 0, + `is_deleted` INT NOT NULL DEFAULT 0, + `user_id` INT NOT NULL, + `object_type` VARCHAR(50) NOT NULL, + `object_id` INT NOT NULL, + `action` VARCHAR(50) NOT NULL, + `meta` TEXT NOT NULL, + FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) +); + +CREATE TABLE IF NOT EXISTS `certificate_authority` +( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `created_at` BIGINT NOT NULL DEFAULT 0, + `updated_at` BIGINT NOT NULL DEFAULT 0, + `is_deleted` INT NOT NULL DEFAULT 0, + `name` VARCHAR(50) NOT NULL, + `acmesh_server` VARCHAR(255) NOT NULL DEFAULT '', + `ca_bundle` VARCHAR(255) NOT NULL DEFAULT '', + `is_wildcard_supported` INT NOT NULL DEFAULT 0, -- specific to each CA, acme v1 doesn't usually have wildcards + `max_domains` INT NOT NULL DEFAULT 5, -- per request + `is_readonly` INT NOT NULL DEFAULT 0 +); + +CREATE TABLE IF NOT EXISTS `dns_provider` +( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `created_at` BIGINT NOT NULL DEFAULT 0, + `updated_at` BIGINT NOT NULL DEFAULT 0, + `is_deleted` INT NOT NULL DEFAULT 0, + `user_id` INT NOT NULL, + `name` VARCHAR(50) NOT NULL, + `acmesh_name` VARCHAR(50) NOT NULL, + `dns_sleep` INT NOT NULL DEFAULT 0, + `meta` TEXT NOT NULL, + FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) +); + +CREATE TABLE IF NOT EXISTS certificate +( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `created_at` BIGINT NOT NULL DEFAULT 0, + `updated_at` BIGINT NOT NULL DEFAULT 0, + `is_deleted` INT NOT NULL DEFAULT 0, + `user_id` INT NOT NULL, + `type` VARCHAR(50) NOT NULL, -- custom,dns,http + `certificate_authority_id` INT, -- 0 for a custom cert + `dns_provider_id` INT, -- 0, for a http or custom cert + `name` VARCHAR(50) NOT NULL, + `domain_names` TEXT NOT NULL, + `expires_on` INT DEFAULT 0, + `status` VARCHAR(50) NOT NULL, -- ready,requesting,failed,provided + `error_message` TEXT NOT NULL, + `meta` TEXT NOT NULL, + `is_ecc` INT NOT NULL DEFAULT 0, + FOREIGN KEY (`user_id`) REFERENCES `user`(`id`), + FOREIGN KEY (`certificate_authority_id`) REFERENCES `certificate_authority`(`id`), + FOREIGN KEY (`dns_provider_id`) REFERENCES `dns_provider`(`id`) +); + +CREATE TABLE IF NOT EXISTS `stream` +( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `created_at` BIGINT NOT NULL DEFAULT 0, + `updated_at` BIGINT NOT NULL DEFAULT 0, + `is_deleted` INT NOT NULL DEFAULT 0, + `user_id` INT NOT NULL, + `listen_interface` VARCHAR(50) NOT NULL, + `incoming_port` INT NOT NULL, + `tcp_forwarding` INT NOT NULL DEFAULT 0, + `udp_forwarding` INT NOT NULL DEFAULT 0, + `advanced_config` TEXT NOT NULL, + `is_disabled` INT NOT NULL DEFAULT 0, + FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) +); + +CREATE TABLE IF NOT EXISTS `nginx_template` +( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `created_at` BIGINT NOT NULL DEFAULT 0, + `updated_at` BIGINT NOT NULL DEFAULT 0, + `is_deleted` INT NOT NULL DEFAULT 0, + `user_id` INT NOT NULL, + `name` VARCHAR(50) NOT NULL, + `type` VARCHAR(50) NOT NULL, + `template` TEXT NOT NULL, + FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) +); + +CREATE TABLE IF NOT EXISTS `upstream` +( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `created_at` BIGINT NOT NULL DEFAULT 0, + `updated_at` BIGINT NOT NULL DEFAULT 0, + `is_deleted` INT NOT NULL DEFAULT 0, + `user_id` INT NOT NULL, + `name` VARCHAR(50) NOT NULL, + `nginx_template_id` INT NOT NULL, + `ip_hash` INT NOT NULL DEFAULT 0, + `ntlm` INT NOT NULL DEFAULT 0, + `keepalive` INT NOT NULL DEFAULT 0, + `keepalive_requests` INT NOT NULL DEFAULT 0, + `keepalive_time` VARCHAR(50) NOT NULL DEFAULT '', + `keepalive_timeout` VARCHAR(50) NOT NULL DEFAULT '', + `advanced_config` TEXT NOT NULL, + `status` VARCHAR(50) NOT NULL DEFAULT '', + `error_message` TEXT NOT NULL, + FOREIGN KEY (`user_id`) REFERENCES `user`(`id`), + FOREIGN KEY (`nginx_template_id`) REFERENCES `nginx_template`(`id`) +); + +CREATE TABLE IF NOT EXISTS `upstream_server` +( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `created_at` BIGINT NOT NULL DEFAULT 0, + `updated_at` BIGINT NOT NULL DEFAULT 0, + `is_deleted` INT NOT NULL DEFAULT 0, + `upstream_id` INT NOT NULL, + `server` VARCHAR(50) NOT NULL, + `weight` INT NOT NULL DEFAULT 0, + `max_conns` INT NOT NULL DEFAULT 0, + `max_fails` INT NOT NULL DEFAULT 0, + `fail_timeout` INT NOT NULL DEFAULT 0, + `is_backup` INT NOT NULL DEFAULT 0, + FOREIGN KEY (`upstream_id`) REFERENCES `upstream`(`id`) +); + +CREATE TABLE IF NOT EXISTS `access_list` +( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `created_at` BIGINT NOT NULL DEFAULT 0, + `updated_at` BIGINT NOT NULL DEFAULT 0, + `is_deleted` INT NOT NULL DEFAULT 0, + `user_id` INT NOT NULL, + `name` VARCHAR(50) NOT NULL, + `meta` TEXT NOT NULL, + FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) +); + +CREATE TABLE IF NOT EXISTS host +( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `created_at` BIGINT NOT NULL DEFAULT 0, + `updated_at` BIGINT NOT NULL DEFAULT 0, + `is_deleted` INT NOT NULL DEFAULT 0, + `user_id` INT NOT NULL, + `type` VARCHAR(50) NOT NULL, + `nginx_template_id` INT NOT NULL, + `listen_interface` VARCHAR(50) NOT NULL DEFAULT '', + `domain_names` TEXT NOT NULL, + `upstream_id` INT NOT NULL DEFAULT 0, + `proxy_scheme` VARCHAR(50) NOT NULL DEFAULT '', + `proxy_host` VARCHAR(50) NOT NULL DEFAULT '', + `proxy_port` INT NOT NULL DEFAULT 0, + `certificate_id` INT NOT NULL DEFAULT 0, + `access_list_id` INT NOT NULL DEFAULT 0, + `ssl_forced` INT NOT NULL DEFAULT 0, + `caching_enabled` INT NOT NULL DEFAULT 0, + `block_exploits` INT NOT NULL DEFAULT 0, + `allow_websocket_upgrade` INT NOT NULL DEFAULT 0, + `http2_support` INT NOT NULL DEFAULT 0, + `hsts_enabled` INT NOT NULL DEFAULT 0, + `hsts_subdomains` INT NOT NULL DEFAULT 0, + `paths` TEXT NOT NULL, + `advanced_config` TEXT NOT NULL, + `status` VARCHAR(50) NOT NULL DEFAULT '', + `error_message` TEXT NOT NULL, + `is_disabled` INT NOT NULL DEFAULT 0, + FOREIGN KEY (`user_id`) REFERENCES `user`(`id`), + FOREIGN KEY (`nginx_template_id`) REFERENCES `nginx_template`(`id`), + FOREIGN KEY (`upstream_id`) REFERENCES `upstream`(`id`), + FOREIGN KEY (`certificate_id`) REFERENCES `certificate`(`id`), + FOREIGN KEY (`access_list_id`) REFERENCES `access_list`(`id`) +); + +-- migrate:down + +-- Not allowed to go down from initial diff --git a/backend/embed/migrations/mysql/20201013035839_initial_data.sql b/backend/embed/migrations/mysql/20201013035839_initial_data.sql new file mode 100644 index 0000000..9908703 --- /dev/null +++ b/backend/embed/migrations/mysql/20201013035839_initial_data.sql @@ -0,0 +1,332 @@ +-- migrate:up + +-- User permissions +INSERT INTO capability ( + name +) VALUES + ("full-admin"), + ("access-lists.view"), + ("access-lists.manage"), + ("audit-log.view"), + ("certificates.view"), + ("certificates.manage"), + ("certificate-authorities.view"), + ("certificate-authorities.manage"), + ("dns-providers.view"), + ("dns-providers.manage"), + ("hosts.view"), + ("hosts.manage"), + ("nginx-templates.view"), + ("nginx-templates.manage"), + ("settings.manage"), + ("streams.view"), + ("streams.manage"), + ("users.manage"); + +-- Default error reporting setting +INSERT INTO setting ( + created_at, + updated_at, + name, + description, + value +) VALUES ( + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + "error-reporting", + "If enabled, any application errors are reported to Sentry. Sensitive information is not sent.", + "true" -- remember this is json +); + +-- Default site +INSERT INTO setting ( + created_at, + updated_at, + name, + description, + value +) VALUES ( + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + "default-site", + "What to show users who hit your Nginx server by default", + '"welcome"' -- remember this is json +); + +-- Default Certificate Authorities + +INSERT INTO certificate_authority ( + created_at, + updated_at, + name, + acmesh_server, + is_wildcard_supported, + max_domains, + is_readonly +) VALUES ( + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + "ZeroSSL", + "zerossl", + 1, + 10, + 1 +), ( + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + "Let's Encrypt", + "https://acme-v02.api.letsencrypt.org/directory", + 1, + 10, + 1 +), ( + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + "Buypass Go SSL", + "https://api.buypass.com/acme/directory", + 0, + 5, + 1 +), ( + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + "SSL.com", + "ssl.com", + 0, + 10, + 1 +), ( + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + "Let's Encrypt (Testing)", + "https://acme-staging-v02.api.letsencrypt.org/directory", + 1, + 10, + 1 +), ( + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + "Buypass Go SSL (Testing)", + "https://api.test4.buypass.no/acme/directory", + 0, + 5, + 1 +); + +-- System User +INSERT INTO user ( + created_at, + updated_at, + name, + nickname, + email, + is_system +) VALUES ( + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + "System", + "System", + "system@localhost", + 1 +); + +-- Host Templates +INSERT INTO nginx_template ( + created_at, + updated_at, + user_id, + name, + type, + template +) VALUES ( + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + (SELECT id FROM user WHERE is_system = 1 LIMIT 1), + "Default Proxy Template", + "proxy", + "# ------------------------------------------------------------ +{{#each Host.DomainNames}} +# {{this}} +{{/each}} +# ------------------------------------------------------------ + +server { + {{#if Config.Ipv4}} + listen 80; + {{/if}} + {{#if Config.Ipv6}} + listen [::]:80; + {{/if}} + + {{#if Certificate.ID}} + {{#if Config.Ipv4}} + listen 443 ssl {{#if Host.HTTP2Support}}http2{{/if}}; + {{/if}} + {{#if Config.Ipv6}} + listen [::]:443 ssl {{#if Host.HTTP2Support}}http2{{/if}}; + {{/if}} + {{/if}} + + server_name {{#each Host.DomainNames}}{{this}} {{/each}}; + + {{#if Certificate.ID}} + include conf.d/include/ssl-ciphers.conf; + {{#if Certificate.IsAcme}} + ssl_certificate {{Certificate.Folder}}/fullchain.pem; + ssl_certificate_key {{Certificate.Folder}}/privkey.pem; + {{else}} + # Custom SSL + ssl_certificate /data/custom_ssl/npm-{{Certicicate.ID}}/fullchain.pem; + ssl_certificate_key /data/custom_ssl/npm-{{Certificate.ID}}/privkey.pem; + {{/if}} + {{/if}} + + {{#if Host.CachingEnabled}} + include conf.d/include/assets.conf; + {{/if}} + + {{#if Host.BlockExploits}} + include conf.d/include/block-exploits.conf; + {{/if}} + + {{#if Certificate.ID}} + {{#if Host.SSLForced}} + {{#if Host.HSTSEnabled}} + # HSTS (ngx_http_headers_module is required) (63072000 seconds = 2 years) + add_header Strict-Transport-Security ""max-age=63072000;{{#if Host.HSTSSubdomains}} includeSubDomains;{{/if}} preload"" always; + {{/if}} + # Force SSL + include conf.d/include/force-ssl.conf; + {{/if}} + {{/if}} + + {{#if Host.AllowWebsocketUpgrade}} + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $http_connection; + proxy_http_version 1.1; + {{/if}} + + access_log /data/logs/host-{{Host.ID}}_access.log proxy; + error_log /data/logs/host-{{Host.ID}}_error.log warn; + + {{Host.AdvancedConfig}} + + # locations ? + + # default location: + location / { + {{#if Host.AccessListID}} + # Authorization + auth_basic ""Authorization required""; + auth_basic_user_file /data/access/{{Host.AccessListID}}; + # access_list.passauth ? todo + {{/if}} + + # Access Rules ? todo + + # Access checks must...? todo + + {{#if Certificate.ID}} + {{#if Host.SSLForced}} + {{#if Host.HSTSEnabled}} + # HSTS (ngx_http_headers_module is required) (63072000 seconds = 2 years) + add_header Strict-Transport-Security ""max-age=63072000;{{#if Host.HSTSSubdomains}} includeSubDomains;{{/if}} preload"" always; + {{/if}} + {{/if}} + {{/if}} + + {{#if Host.AllowWebsocketUpgrade}} + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $http_connection; + {{/if}} + + # Proxy! + add_header X-Served-By $host; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Scheme $scheme; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_http_version 1.1; + + {{#if Upstream.ID}} + # upstream + proxy_pass {{Host.ProxyScheme}}://npm_upstream_{{Upstream.ID}}; + {{else}} + # proxy a single host + proxy_pass {{Host.ProxyScheme}}://{{Host.ProxyHost}}:{{Host.ProxyPort}}; + {{/if}} + } + + # Legacy Custom Configuration + include /data/nginx/custom/server_proxy[.]conf; +} +" +), ( + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + (SELECT id FROM user WHERE is_system = 1 LIMIT 1), + "Default Redirect Template", + "redirect", + "# this is a redirect template" +), ( + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + (SELECT id FROM user WHERE is_system = 1 LIMIT 1), + "Default Dead Template", + "dead", + "# this is a dead template" +), ( + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + (SELECT id FROM user WHERE is_system = 1 LIMIT 1), + "Default Stream Template", + "stream", + "# this is a stream template" +), ( + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000), + (SELECT id FROM user WHERE is_system = 1 LIMIT 1), + "Default Upstream Template", + "upstream", + "# ------------------------------------------------------------ +# Upstream {{Upstream.ID}}: {{Upstream.Name}} +# ------------------------------------------------------------ + +upstream npm_upstream_{{Upstream.ID}} { + + {{#if Upstream.IPHash~}} + ip_hash; + {{~/if}} + + {{#if Upstream.NTLM~}} + ntlm; + {{~/if}} + + {{#if Upstream.Keepalive~}} + keepalive {{Upstream.Keepalive}}; + {{~/if}} + + {{#if Upstream.KeepaliveRequests~}} + keepalive_requests {{Upstream.KeepaliveRequests}}; + {{~/if}} + + {{#if Upstream.KeepaliveTime~}} + keepalive_time {{Upstream.KeepaliveTime}}; + {{~/if}} + + {{#if Upstream.KeepaliveTimeout~}} + keepalive_timeout {{Upstream.KeepaliveTimeout}}; + {{~/if}} + + {{Upstream.AdvancedConfig}} + + {{#each Upstream.Servers~}} + {{#unless IsDeleted~}} + server {{Server}} {{#if Weight}}weight={{Weight}} {{/if}}{{#if MaxConns}}max_conns={{MaxConns}} {{/if}}{{#if MaxFails}}max_fails={{MaxFails}} {{/if}}{{#if FailTimeout}}fail_timeout={{FailTimeout}} {{/if}}{{#if Backup}}backup{{/if}}; + {{/unless}} + {{/each}} +} +" +); + +-- migrate:down diff --git a/backend/embed/migrations/postgres/20201013035318_initial_schema.sql b/backend/embed/migrations/postgres/20201013035318_initial_schema.sql new file mode 100644 index 0000000..4529e0c --- /dev/null +++ b/backend/embed/migrations/postgres/20201013035318_initial_schema.sql @@ -0,0 +1,212 @@ +-- migrate:up + +CREATE TABLE "jwt_keys" ( + "id" SERIAL PRIMARY KEY, + "created_at" BIGINT NOT NULL DEFAULT 0, + "updated_at" BIGINT NOT NULL DEFAULT 0, + "is_deleted" INTEGER NOT NULL DEFAULT 0, + "public_key" TEXT NOT NULL, + "private_key" TEXT NOT NULL +); + +CREATE TABLE "user" ( + "id" SERIAL PRIMARY KEY, + "created_at" BIGINT NOT NULL DEFAULT 0, + "updated_at" BIGINT NOT NULL DEFAULT 0, + "is_deleted" INTEGER NOT NULL DEFAULT 0, + "name" VARCHAR(50) NOT NULL, + "nickname" VARCHAR(50) NOT NULL, + "email" VARCHAR(255) NOT NULL, + "is_system" INTEGER NOT NULL DEFAULT 0, + "is_disabled" INTEGER NOT NULL DEFAULT 0 +); + +CREATE TABLE "capability" ( + "name" TEXT NOT NULL PRIMARY KEY, + UNIQUE ("name") +); + +CREATE TABLE "user_has_capability" ( + "user_id" INTEGER NOT NULL, + "capability_name" TEXT NOT NULL REFERENCES "capability"("name"), + UNIQUE ("user_id", "capability_name") +); + +CREATE TABLE "auth" ( + "id" SERIAL PRIMARY KEY, + "created_at" BIGINT NOT NULL DEFAULT 0, + "updated_at" BIGINT NOT NULL DEFAULT 0, + "is_deleted" INTEGER NOT NULL DEFAULT 0, + "user_id" INTEGER NOT NULL REFERENCES "user"("id"), + "type" VARCHAR(50) NOT NULL, + "secret" VARCHAR(255) NOT NULL, + UNIQUE ("user_id", "type") +); + +CREATE TABLE "setting" ( + "id" SERIAL PRIMARY KEY, + "created_at" BIGINT NOT NULL DEFAULT 0, + "updated_at" BIGINT NOT NULL DEFAULT 0, + "is_deleted" INTEGER NOT NULL DEFAULT 0, + "name" VARCHAR(50) NOT NULL, + "description" VARCHAR(255) NOT NULL DEFAULT '', + "value" TEXT NOT NULL, + UNIQUE ("name") +); + +CREATE TABLE "audit_log" ( + "id" SERIAL PRIMARY KEY, + "created_at" BIGINT NOT NULL DEFAULT 0, + "updated_at" BIGINT NOT NULL DEFAULT 0, + "is_deleted" INTEGER NOT NULL DEFAULT 0, + "user_id" INTEGER NOT NULL REFERENCES "user"("id"), + "object_type" VARCHAR(50) NOT NULL, + "object_id" INTEGER NOT NULL, + "action" VARCHAR(50) NOT NULL, + "meta" TEXT NOT NULL +); + +CREATE TABLE "certificate_authority" ( + "id" SERIAL PRIMARY KEY, + "created_at" BIGINT NOT NULL DEFAULT 0, + "updated_at" BIGINT NOT NULL DEFAULT 0, + "is_deleted" INTEGER NOT NULL DEFAULT 0, + "name" VARCHAR(50) NOT NULL, + "acmesh_server" VARCHAR(255) NOT NULL DEFAULT '', + "ca_bundle" VARCHAR(255) NOT NULL DEFAULT '', + "is_wildcard_supported" INTEGER NOT NULL DEFAULT 0, -- specific to each CA, acme v1 doesn't usually have wildcards + "max_domains" INTEGER NOT NULL DEFAULT 5, -- per request + "is_readonly" INTEGER NOT NULL DEFAULT 0 +); + +CREATE TABLE "dns_provider" ( + "id" SERIAL PRIMARY KEY, + "created_at" BIGINT NOT NULL DEFAULT 0, + "updated_at" BIGINT NOT NULL DEFAULT 0, + "is_deleted" INTEGER NOT NULL DEFAULT 0, + "user_id" INTEGER NOT NULL REFERENCES "user"("id"), + "name" VARCHAR(50) NOT NULL, + "acmesh_name" VARCHAR(50) NOT NULL, + "dns_sleep" INTEGER NOT NULL DEFAULT 0, + "meta" TEXT NOT NULL +); + +CREATE TABLE "certificate" ( + "id" SERIAL PRIMARY KEY, + "created_at" BIGINT NOT NULL DEFAULT 0, + "updated_at" BIGINT NOT NULL DEFAULT 0, + "is_deleted" INTEGER NOT NULL DEFAULT 0, + "user_id" INTEGER NOT NULL REFERENCES "user"("id"), + "type" VARCHAR(50) NOT NULL, -- custom,dns,http + "certificate_authority_id" INTEGER REFERENCES "certificate_authority"("id"), -- 0 for a custom cert + "dns_provider_id" INTEGER REFERENCES "dns_provider"("id"), -- 0, for a http or custom cert + "name" VARCHAR(50) NOT NULL, + "domain_names" TEXT NOT NULL, + "expires_on" INTEGER DEFAULT 0, + "status" VARCHAR(50) NOT NULL, -- ready,requesting,failed,provided + "error_message" TEXT NOT NULL DEFAULT '', + "meta" TEXT NOT NULL, + "is_ecc" INTEGER NOT NULL DEFAULT 0 +); + +CREATE TABLE "stream" ( + "id" SERIAL PRIMARY KEY, + "created_at" BIGINT NOT NULL DEFAULT 0, + "updated_at" BIGINT NOT NULL DEFAULT 0, + "is_deleted" INTEGER NOT NULL DEFAULT 0, + "user_id" INTEGER NOT NULL REFERENCES "user"("id"), + "listen_interface" VARCHAR(50) NOT NULL, + "incoming_port" INTEGER NOT NULL, + "tcp_forwarding" INTEGER NOT NULL DEFAULT 0, + "udp_forwarding" INTEGER NOT NULL DEFAULT 0, + "advanced_config" TEXT NOT NULL, + "is_disabled" INTEGER NOT NULL DEFAULT 0 +); + +CREATE TABLE "nginx_template" ( + "id" SERIAL PRIMARY KEY, + "created_at" BIGINT NOT NULL DEFAULT 0, + "updated_at" BIGINT NOT NULL DEFAULT 0, + "is_deleted" INTEGER NOT NULL DEFAULT 0, + "user_id" INTEGER NOT NULL REFERENCES "user"("id"), + "name" VARCHAR(50) NOT NULL, + "type" VARCHAR(50) NOT NULL, + "template" TEXT NOT NULL +); + +CREATE TABLE "upstream" ( + "id" SERIAL PRIMARY KEY, + "created_at" BIGINT NOT NULL DEFAULT 0, + "updated_at" BIGINT NOT NULL DEFAULT 0, + "is_deleted" INTEGER NOT NULL DEFAULT 0, + "user_id" INTEGER NOT NULL REFERENCES "user"("id"), + "name" VARCHAR(50) NOT NULL, + "nginx_template_id" INTEGER NOT NULL REFERENCES "nginx_template"("id"), + "ip_hash" INTEGER NOT NULL DEFAULT 0, + "ntlm" INTEGER NOT NULL DEFAULT 0, + "keepalive" INTEGER NOT NULL DEFAULT 0, + "keepalive_requests" INTEGER NOT NULL DEFAULT 0, + "keepalive_time" VARCHAR(50) NOT NULL DEFAULT '', + "keepalive_timeout" VARCHAR(50) NOT NULL DEFAULT '', + "advanced_config" TEXT NOT NULL, + "status" VARCHAR(50) NOT NULL DEFAULT '', + "error_message" TEXT NOT NULL DEFAULT '' +); + +CREATE TABLE "upstream_server" ( + "id" SERIAL PRIMARY KEY, + "created_at" BIGINT NOT NULL DEFAULT 0, + "updated_at" BIGINT NOT NULL DEFAULT 0, + "is_deleted" INTEGER NOT NULL DEFAULT 0, + "upstream_id" INTEGER NOT NULL REFERENCES "upstream"("id"), + "server" VARCHAR(50) NOT NULL, + "weight" INTEGER NOT NULL DEFAULT 0, + "max_conns" INTEGER NOT NULL DEFAULT 0, + "max_fails" INTEGER NOT NULL DEFAULT 0, + "fail_timeout" INTEGER NOT NULL DEFAULT 0, + "is_backup" INTEGER NOT NULL DEFAULT 0 +); + +CREATE TABLE "access_list" ( + "id" SERIAL PRIMARY KEY, + "created_at" BIGINT NOT NULL DEFAULT 0, + "updated_at" BIGINT NOT NULL DEFAULT 0, + "is_deleted" INTEGER NOT NULL DEFAULT 0, + "user_id" INTEGER NOT NULL REFERENCES "user"("id"), + "name" VARCHAR(50) NOT NULL, + "meta" TEXT NOT NULL +); + +CREATE TABLE "host" ( + "id" SERIAL PRIMARY KEY, + "created_at" BIGINT NOT NULL DEFAULT 0, + "updated_at" BIGINT NOT NULL DEFAULT 0, + "is_deleted" INTEGER NOT NULL DEFAULT 0, + "user_id" INTEGER NOT NULL REFERENCES "user"("id"), + "type" TEXT NOT NULL, + "nginx_template_id" INTEGER NOT NULL REFERENCES "nginx_template"("id"), + "listen_interface" TEXT NOT NULL DEFAULT '', + "domain_names" TEXT NOT NULL, + "upstream_id" INTEGER NOT NULL DEFAULT 0 REFERENCES "upstream"("id"), + "proxy_scheme" TEXT NOT NULL DEFAULT '', + "proxy_host" TEXT NOT NULL DEFAULT '', + "proxy_port" INTEGER NOT NULL DEFAULT 0, + "certificate_id" INTEGER NOT NULL DEFAULT 0 REFERENCES "certificate"("id"), + "access_list_id" INTEGER NOT NULL DEFAULT 0 REFERENCES "access_list"("id"), + "ssl_forced" INTEGER NOT NULL DEFAULT 0, + "caching_enabled" INTEGER NOT NULL DEFAULT 0, + "block_exploits" INTEGER NOT NULL DEFAULT 0, + "allow_websocket_upgrade" INTEGER NOT NULL DEFAULT 0, + "http2_support" INTEGER NOT NULL DEFAULT 0, + "hsts_enabled" INTEGER NOT NULL DEFAULT 0, + "hsts_subdomains" INTEGER NOT NULL DEFAULT 0, + "paths" TEXT NOT NULL DEFAULT '', + "advanced_config" TEXT NOT NULL DEFAULT '', + "status" TEXT NOT NULL DEFAULT '', + "error_message" TEXT NOT NULL DEFAULT '', + "is_disabled" INTEGER NOT NULL DEFAULT 0 +); + +-- migrate:down + +-- Not allowed to go down from initial diff --git a/backend/embed/migrations/postgres/20201013035839_initial_data.sql b/backend/embed/migrations/postgres/20201013035839_initial_data.sql new file mode 100644 index 0000000..02c0bf8 --- /dev/null +++ b/backend/embed/migrations/postgres/20201013035839_initial_data.sql @@ -0,0 +1,332 @@ +-- migrate:up + +-- User permissions +INSERT INTO "capability" ( + "name" +) VALUES + ('full-admin'), + ('access-lists.view'), + ('access-lists.manage'), + ('audit-log.view'), + ('certificates.view'), + ('certificates.manage'), + ('certificate-authorities.view'), + ('certificate-authorities.manage'), + ('dns-providers.view'), + ('dns-providers.manage'), + ('hosts.view'), + ('hosts.manage'), + ('nginx-templates.view'), + ('nginx-templates.manage'), + ('settings.manage'), + ('streams.view'), + ('streams.manage'), + ('users.manage'); + +-- Default error reporting setting +INSERT INTO "setting" ( + "created_at", + "updated_at", + "name", + "description", + "value" +) VALUES ( + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + 'error-reporting', + 'If enabled, any application errors are reported to Sentry. Sensitive information is not sent.', + 'true' -- remember this is json +); + +-- Default site +INSERT INTO "setting" ( + "created_at", + "updated_at", + "name", + "description", + "value" +) VALUES ( + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + 'default-site', + 'What to show users who hit your Nginx server by default', + '"welcome"' -- remember this is json +); + +-- Default Certificate Authorities + +INSERT INTO "certificate_authority" ( + "created_at", + "updated_at", + "name", + "acmesh_server", + "is_wildcard_supported", + "max_domains", + "is_readonly" +) VALUES ( + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + 'ZeroSSL', + 'zerossl', + 1, + 10, + 1 +), ( + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + 'Let''s Encrypt', + 'https://acme-v02.api.letsencrypt.org/directory', + 1, + 10, + 1 +), ( + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + 'Buypass Go SSL', + 'https://api.buypass.com/acme/directory', + 0, + 5, + 1 +), ( + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + 'SSL.com', + 'ssl.com', + 0, + 10, + 1 +), ( + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + 'Let''s Encrypt (Testing)', + 'https://acme-staging-v02.api.letsencrypt.org/directory', + 1, + 10, + 1 +), ( + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + 'Buypass Go SSL (Testing)', + 'https://api.test4.buypass.no/acme/directory', + 0, + 5, + 1 +); + +-- System User +INSERT INTO "user" ( + "created_at", + "updated_at", + "name", + "nickname", + "email", + "is_system" +) VALUES ( + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + 'System', + 'System', + 'system@localhost', + 1 +); + +-- Host Templates +INSERT INTO "nginx_template" ( + "created_at", + "updated_at", + "user_id", + "name", + "type", + "template" +) VALUES ( + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + (SELECT "id" FROM "user" WHERE "is_system" = 1 LIMIT 1), + 'Default Proxy Template', + 'proxy', + '# ------------------------------------------------------------ +{{#each Host.DomainNames}} +# {{this}} +{{/each}} +# ------------------------------------------------------------ + +server { + {{#if Config.Ipv4}} + listen 80; + {{/if}} + {{#if Config.Ipv6}} + listen [::]:80; + {{/if}} + + {{#if Certificate.ID}} + {{#if Config.Ipv4}} + listen 443 ssl {{#if Host.HTTP2Support}}http2{{/if}}; + {{/if}} + {{#if Config.Ipv6}} + listen [::]:443 ssl {{#if Host.HTTP2Support}}http2{{/if}}; + {{/if}} + {{/if}} + + server_name {{#each Host.DomainNames}}{{this}} {{/each}}; + + {{#if Certificate.ID}} + include conf.d/include/ssl-ciphers.conf; + {{#if Certificate.IsAcme}} + ssl_certificate {{Certificate.Folder}}/fullchain.pem; + ssl_certificate_key {{Certificate.Folder}}/privkey.pem; + {{else}} + # Custom SSL + ssl_certificate /data/custom_ssl/npm-{{Certicicate.ID}}/fullchain.pem; + ssl_certificate_key /data/custom_ssl/npm-{{Certificate.ID}}/privkey.pem; + {{/if}} + {{/if}} + + {{#if Host.CachingEnabled}} + include conf.d/include/assets.conf; + {{/if}} + + {{#if Host.BlockExploits}} + include conf.d/include/block-exploits.conf; + {{/if}} + + {{#if Certificate.ID}} + {{#if Host.SSLForced}} + {{#if Host.HSTSEnabled}} + # HSTS (ngx_http_headers_module is required) (63072000 seconds = 2 years) + add_header Strict-Transport-Security "max-age=63072000;{{#if Host.HSTSSubdomains}} includeSubDomains;{{/if}} preload" always; + {{/if}} + # Force SSL + include conf.d/include/force-ssl.conf; + {{/if}} + {{/if}} + + {{#if Host.AllowWebsocketUpgrade}} + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $http_connection; + proxy_http_version 1.1; + {{/if}} + + access_log /data/logs/host-{{Host.ID}}_access.log proxy; + error_log /data/logs/host-{{Host.ID}}_error.log warn; + + {{Host.AdvancedConfig}} + + # locations ? + + # default location: + location / { + {{#if Host.AccessListID}} + # Authorization + auth_basic "Authorization required"; + auth_basic_user_file /data/access/{{Host.AccessListID}}; + # access_list.passauth ? todo + {{/if}} + + # Access Rules ? todo + + # Access checks must...? todo + + {{#if Certificate.ID}} + {{#if Host.SSLForced}} + {{#if Host.HSTSEnabled}} + # HSTS (ngx_http_headers_module is required) (63072000 seconds = 2 years) + add_header Strict-Transport-Security "max-age=63072000;{{#if Host.HSTSSubdomains}} includeSubDomains;{{/if}} preload" always; + {{/if}} + {{/if}} + {{/if}} + + {{#if Host.AllowWebsocketUpgrade}} + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $http_connection; + {{/if}} + + # Proxy! + add_header X-Served-By $host; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Scheme $scheme; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_http_version 1.1; + + {{#if Upstream.ID}} + # upstream + proxy_pass {{Host.ProxyScheme}}://npm_upstream_{{Upstream.ID}}; + {{else}} + # proxy a single host + proxy_pass {{Host.ProxyScheme}}://{{Host.ProxyHost}}:{{Host.ProxyPort}}; + {{/if}} + } + + # Legacy Custom Configuration + include /data/nginx/custom/server_proxy[.]conf; +} +' +), ( + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + (SELECT "id" FROM "user" WHERE "is_system" = 1 LIMIT 1), + 'Default Redirect Template', + 'redirect', + '# this is a redirect template' +), ( + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + (SELECT "id" FROM "user" WHERE "is_system" = 1 LIMIT 1), + 'Default Dead Template', + 'dead', + '# this is a dead template' +), ( + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + (SELECT "id" FROM "user" WHERE "is_system" = 1 LIMIT 1), + 'Default Stream Template', + 'stream', + '# this is a stream template' +), ( + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + EXTRACT(EPOCH FROM TIMESTAMP '2011-05-17 10:40:28.876944') * 1000, + (SELECT "id" FROM "user" WHERE "is_system" = 1 LIMIT 1), + 'Default Upstream Template', + 'upstream', + '# ------------------------------------------------------------ +# Upstream {{Upstream.ID}}: {{Upstream.Name}} +# ------------------------------------------------------------ + +upstream npm_upstream_{{Upstream.ID}} { + + {{#if Upstream.IPHash~}} + ip_hash; + {{~/if}} + + {{#if Upstream.NTLM~}} + ntlm; + {{~/if}} + + {{#if Upstream.Keepalive~}} + keepalive {{Upstream.Keepalive}}; + {{~/if}} + + {{#if Upstream.KeepaliveRequests~}} + keepalive_requests {{Upstream.KeepaliveRequests}}; + {{~/if}} + + {{#if Upstream.KeepaliveTime~}} + keepalive_time {{Upstream.KeepaliveTime}}; + {{~/if}} + + {{#if Upstream.KeepaliveTimeout~}} + keepalive_timeout {{Upstream.KeepaliveTimeout}}; + {{~/if}} + + {{Upstream.AdvancedConfig}} + + {{#each Upstream.Servers~}} + {{#unless IsDeleted~}} + server {{Server}} {{#if Weight}}weight={{Weight}} {{/if}}{{#if MaxConns}}max_conns={{MaxConns}} {{/if}}{{#if MaxFails}}max_fails={{MaxFails}} {{/if}}{{#if FailTimeout}}fail_timeout={{FailTimeout}} {{/if}}{{#if Backup}}backup{{/if}}; + {{/unless}} + {{/each}} +} +' +); + +-- migrate:down diff --git a/backend/embed/migrations/sqlite/20201013035318_initial_schema.sql b/backend/embed/migrations/sqlite/20201013035318_initial_schema.sql index aeee284..8862c53 100644 --- a/backend/embed/migrations/sqlite/20201013035318_initial_schema.sql +++ b/backend/embed/migrations/sqlite/20201013035318_initial_schema.sql @@ -1,6 +1,6 @@ -- migrate:up -CREATE TABLE IF NOT EXISTS `keys` +CREATE TABLE IF NOT EXISTS `jwt_keys` ( id INTEGER PRIMARY KEY AUTOINCREMENT, created_at INTEGER NOT NULL DEFAULT 0, @@ -110,15 +110,15 @@ CREATE TABLE IF NOT EXISTS `certificate` created_at INTEGER NOT NULL DEFAULT 0, updated_at INTEGER NOT NULL DEFAULT 0, is_deleted INTEGER NOT NULL DEFAULT 0, - type TEXT NOT NULL, -- custom,dns,http user_id INTEGER NOT NULL, + type TEXT NOT NULL, -- custom,dns,http certificate_authority_id INTEGER, -- 0 for a custom cert dns_provider_id INTEGER, -- 0, for a http or custom cert name TEXT NOT NULL, domain_names TEXT NOT NULL, expires_on INTEGER DEFAULT 0, status TEXT NOT NULL, -- ready,requesting,failed,provided - error_message text NOT NULL DEFAULT "", + error_message TEXT NOT NULL DEFAULT "", meta TEXT NOT NULL, is_ecc INTEGER NOT NULL DEFAULT 0, FOREIGN KEY (user_id) REFERENCES user (id), @@ -142,6 +142,19 @@ CREATE TABLE IF NOT EXISTS `stream` FOREIGN KEY (user_id) REFERENCES user (id) ); +CREATE TABLE IF NOT EXISTS `nginx_template` +( + id INTEGER PRIMARY KEY AUTOINCREMENT, + created_at INTEGER NOT NULL DEFAULT 0, + updated_at INTEGER NOT NULL DEFAULT 0, + is_deleted INTEGER NOT NULL DEFAULT 0, + user_id INTEGER NOT NULL, + name TEXT NOT NULL, + type TEXT NOT NULL, + template TEXT NOT NULL, + FOREIGN KEY (user_id) REFERENCES user (id) +); + CREATE TABLE IF NOT EXISTS `upstream` ( id INTEGER PRIMARY KEY AUTOINCREMENT, @@ -192,19 +205,6 @@ CREATE TABLE IF NOT EXISTS `access_list` FOREIGN KEY (user_id) REFERENCES user (id) ); -CREATE TABLE IF NOT EXISTS `nginx_template` -( - id INTEGER PRIMARY KEY AUTOINCREMENT, - created_at INTEGER NOT NULL DEFAULT 0, - updated_at INTEGER NOT NULL DEFAULT 0, - is_deleted INTEGER NOT NULL DEFAULT 0, - user_id INTEGER NOT NULL, - name TEXT NOT NULL, - type TEXT NOT NULL, - template TEXT NOT NULL, - FOREIGN KEY (user_id) REFERENCES user (id) -); - CREATE TABLE IF NOT EXISTS `host` ( id INTEGER PRIMARY KEY AUTOINCREMENT, diff --git a/backend/internal/config/db.go b/backend/internal/config/db.go index 55dd92b..0b08327 100644 --- a/backend/internal/config/db.go +++ b/backend/internal/config/db.go @@ -18,7 +18,7 @@ type db struct { Username string `json:"username" envconfig:"optional,default="` Password string `json:"password" envconfig:"optional,default="` Name string `json:"name" envconfig:"optional,default="` - SSLMode string `json:"sslmode" envconfig:"optional,default=deisable"` + SSLMode string `json:"sslmode" envconfig:"optional,default=disable"` } // GetDriver returns the lowercase driver name diff --git a/backend/internal/database/migrator.go b/backend/internal/database/migrator.go index 9e41535..0622d18 100644 --- a/backend/internal/database/migrator.go +++ b/backend/internal/database/migrator.go @@ -9,6 +9,7 @@ import ( "npm/internal/logger" "github.com/amacneil/dbmate/v2/pkg/dbmate" + _ "github.com/amacneil/dbmate/v2/pkg/driver/mysql" _ "github.com/amacneil/dbmate/v2/pkg/driver/postgres" _ "github.com/amacneil/dbmate/v2/pkg/driver/sqlite" ) diff --git a/backend/internal/jwt/keys_db.go b/backend/internal/jwt/keys_db.go index f00e727..501f70c 100644 --- a/backend/internal/jwt/keys_db.go +++ b/backend/internal/jwt/keys_db.go @@ -16,7 +16,7 @@ type KeysModel struct { // TableName overrides the table name used by gorm func (KeysModel) TableName() string { - return "keys" + return "jwt_keys" } // LoadByID will load from an ID diff --git a/docker/docker-compose.ci.mysql.yml b/docker/docker-compose.ci.mysql.yml new file mode 100644 index 0000000..c77e9d6 --- /dev/null +++ b/docker/docker-compose.ci.mysql.yml @@ -0,0 +1,25 @@ +# WARNING: This is a CI docker-compose file used for building and testing of the entire app, it should not be used for production. +version: '3.8' +services: + + fullstack: + environment: + NPM_DB_DRIVER: 'mysql' + NPM_DB_HOST: 'db-mysql' + NPM_DB_PORT: '3306' + NPM_DB_USERNAME: 'npm' + NPM_DB_PASSWORD: 'npmpass' + NPM_DB_NAME: 'npm' + + db-mysql: + image: mysql:latest + environment: + MYSQL_ROOT_PASSWORD: 'npm' + MYSQL_DATABASE: 'npm' + MYSQL_USER: 'npm' + MYSQL_PASSWORD: 'npmpass' + volumes: + - mysql_vol:/var/lib/mysql + +volumes: + mysql_vol: diff --git a/docker/docker-compose.ci.postgres.yml b/docker/docker-compose.ci.postgres.yml new file mode 100644 index 0000000..6c787b5 --- /dev/null +++ b/docker/docker-compose.ci.postgres.yml @@ -0,0 +1,25 @@ +# WARNING: This is a CI docker-compose file used for building and testing of the entire app, it should not be used for production. +version: '3.8' +services: + + fullstack: + environment: + NPM_DB_DRIVER: 'postgres' + NPM_DB_HOST: 'db-postgres' + NPM_DB_PORT: '5432' + NPM_DB_USERNAME: 'npm' + NPM_DB_PASSWORD: 'npmpass' + NPM_DB_NAME: 'npm' + NPM_DB_SSLMODE: 'disable' + + db-postgres: + image: postgres:15 + environment: + POSTGRES_USER: 'npm' + POSTGRES_PASSWORD: 'npmpass' + POSTGRES_DB: 'npm' + volumes: + - psql_vol:/var/lib/postgresql/data + +volumes: + psql_vol: diff --git a/docker/docker-compose.ci.yml b/docker/docker-compose.ci.yml index c896149..3b80c66 100644 --- a/docker/docker-compose.ci.yml +++ b/docker/docker-compose.ci.yml @@ -5,9 +5,10 @@ services: fullstack: image: ${IMAGE}:${BRANCH_LOWER}-ci-${BUILD_NUMBER} environment: - - NPM_LOG_LEVEL=debug - - NPM_LOG_FORMAT=json - - NPM_DISABLE_IPV6=true + NPM_DB_DRIVER: 'sqlite' + NPM_LOG_LEVEL: 'debug' + NPM_LOG_FORMAT: 'json' + NPM_DISABLE_IPV6: 'true' volumes: - '/etc/localtime:/etc/localtime:ro' - npm_data_ci:/data