diff --git a/.drone-manifest-fic-nginx.yml b/.drone-manifest-fic-nginx.yml new file mode 100644 index 00000000..cbd2dcce --- /dev/null +++ b/.drone-manifest-fic-nginx.yml @@ -0,0 +1,22 @@ +image: nemunaire/fic-nginx:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}} +{{#if build.tags}} +tags: +{{#each build.tags}} + - {{this}} +{{/each}} +{{/if}} +manifests: + - image: nemunaire/fic-nginx:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64 + platform: + architecture: amd64 + os: linux + - image: nemunaire/fic-nginx:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64 + platform: + architecture: arm64 + os: linux + variant: v8 + - image: nemunaire/fic-nginx:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm + platform: + architecture: arm + os: linux + variant: v7 diff --git a/.drone.yml b/.drone.yml index ccb5a1a9..1fef3ccd 100644 --- a/.drone.yml +++ b/.drone.yml @@ -151,6 +151,21 @@ steps: branch: - master + - name: docker frontend nginx + image: plugins/docker + settings: + username: + from_secret: docker_username + password: + from_secret: docker_password + repo: nemunaire/fic-nginx + auto_tag: true + auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} + dockerfile: Dockerfile-nginx + when: + branch: + - master + - name: docker dashboard image: plugins/docker settings: @@ -331,6 +346,21 @@ steps: branch: - master + - name: docker frontend nginx + image: plugins/docker + settings: + username: + from_secret: docker_username + password: + from_secret: docker_password + repo: nemunaire/fic-nginx + auto_tag: true + auto_tag_suffix: ${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} + dockerfile: Dockerfile-nginx + when: + branch: + - master + - name: docker dashboard image: plugins/docker settings: @@ -414,6 +444,17 @@ steps: password: from_secret: docker_password + - name: publish frontend nginx + image: plugins/manifest + settings: + auto_tag: true + ignore_missing: true + spec: .drone-manifest-fic-nginx.yml + username: + from_secret: docker_username + password: + from_secret: docker_password + - name: publish dashboard image: plugins/manifest settings: diff --git a/Dockerfile-nginx b/Dockerfile-nginx new file mode 100644 index 00000000..eadeacb3 --- /dev/null +++ b/Dockerfile-nginx @@ -0,0 +1,11 @@ +FROM nginx:stable-alpine + +ENV HOST_FRONTEND=frontend:8080 HOST_ADMIN=admin:8081 HOST_DASHBOARD=dashboard:8082 HOST_QA=qa:8083 \ + PATH_FILES=/srv/FILES PATH_STATIC=/srv/htdocs-frontend PATH_SETTINGS=/srv/SETTINGS PATH_TEAMS=/srv/TEAMS + +EXPOSE 80 + +COPY configs/fic-auth-docker.conf /etc/nginx/auth.conf +COPY configs/nginx-docker.conf /etc/nginx/templates/default.conf.template + +COPY frontend/static /srv/htdocs-frontend diff --git a/configs/fic-auth-docker.conf b/configs/fic-auth-docker.conf new file mode 100644 index 00000000..6470cb3c --- /dev/null +++ b/configs/fic-auth-docker.conf @@ -0,0 +1 @@ +set $team "$http_x_fic_user"; diff --git a/configs/nginx-docker.conf b/configs/nginx-docker.conf new file mode 100644 index 00000000..0a36cbbd --- /dev/null +++ b/configs/nginx-docker.conf @@ -0,0 +1,225 @@ +server_tokens off; +proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=STATIC:10m inactive=24h max_size=1g; +proxy_connect_timeout 1s; + +server { + listen 80 default; + listen [::]:80 default; + + root ${PATH_STATIC}; + + error_page 401 /welcome.html; + error_page 403 404 /e404.html; + error_page 413 404 /e413.html; + error_page 500 502 504 /e500.html; + + location = / { + include /etc/nginx/auth.conf; + } + location = /index.html { + include /etc/nginx/auth.conf; + } + location = /welcome.html { + internal; + if ($http_accept ~ "^application/json") { + rewrite ^/(.*).html$ /$1.json; + } + } + location = /e404.html { + internal; + if ($http_accept ~ "^application/json") { + rewrite ^/(.*).html$ /$1.json; + } + } + location = /e413.html { + internal; + if ($http_accept ~ "^application/json") { + rewrite ^/(.*).html$ /$1.json; + } + } + location = /e500.html { + internal; + if ($http_accept ~ "^application/json") { + rewrite ^/(.*).html$ /$1.json; + } + } + + location ~ ^/[A-Z] { + include /etc/nginx/auth.conf; + + rewrite ^/.*$ /index.html; + } + location /edit { + include /etc/nginx/auth.conf; + + rewrite ^/.*$ /index.html; + } + location /issue { + include /etc/nginx/auth.conf; + + rewrite ^/.*$ /index.html; + } + location /issues { + include /etc/nginx/auth.conf; + + rewrite ^/.*$ /index.html; + } + location /rank { + include /etc/nginx/auth.conf; + + rewrite ^/.*$ /index.html; + } + location /rules { + include /etc/nginx/auth.conf; + + rewrite ^/.*$ /index.html; + } + location /tags/ { + include /etc/nginx/auth.conf; + + rewrite ^/.*$ /index.html; + } + location /register { + include /etc/nginx/auth.conf; + + rewrite ^/.*$ /index.html; + } + + location /files/ { + alias ${PATH_FILES}/; + sendfile on; + tcp_nodelay on; + } + + location /wait.json { + include /etc/nginx/auth.conf; + + root ${PATH_TEAMS}/$team/; + expires epoch; + add_header Cache-Control no-cache; + } + location /stats.json { + root ${PATH_TEAMS}/; + expires epoch; + add_header Cache-Control no-cache; + } + location /my.json { + include /etc/nginx/auth.conf; + + root ${PATH_TEAMS}/$team/; + expires epoch; + add_header Cache-Control no-cache; + + if (!-f $document_root/../../startingblock/started) { + rewrite ^/ /wait.json; + } + } + location /issues.json { + include /etc/nginx/auth.conf; + + root ${PATH_TEAMS}/$team/; + expires epoch; + add_header Cache-Control no-cache; + } + location /teams.json { + root ${PATH_TEAMS}; + expires epoch; + add_header Cache-Control no-cache; + } + location /themes.json { + root ${PATH_TEAMS}; + expires epoch; + add_header Cache-Control no-cache; + } + location /settings.json { + root ${PATH_SETTINGS}/; + expires epoch; + add_header X-FIC-time $msec; + add_header Cache-Control no-cache; + } + + location /submit/ { + include /etc/nginx/auth.conf; + + rewrite ^/submit/(.*)$ /submission/$team/$1 break; + + proxy_pass http://${HOST_FRONTEND}/; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_redirect off; + } + + location /submit/name { + include /etc/nginx/auth.conf; + + rewrite ^/submit/.*$ /chname/$team break; + + proxy_pass http://${HOST_FRONTEND}/; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_redirect off; + } + + location /registration { + include /etc/nginx/auth.conf; + + rewrite ^/registration /registration/$team break; + + proxy_pass http://${HOST_FRONTEND}; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_redirect off; + } + + location /openhint/ { + include /etc/nginx/auth.conf; + + rewrite ^/openhint/(.*)$ /openhint/$team/$1 break; + + proxy_pass http://${HOST_FRONTEND}/; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_redirect off; + } + + location /wantchoices/ { + include /etc/nginx/auth.conf; + + rewrite ^/wantchoices/(.*)$ /wantchoices/$team/$1 break; + + proxy_pass http://${HOST_FRONTEND}/; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_redirect off; + } + + location /dashboard/ { + proxy_pass http://${HOST_DASHBOARD}; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_redirect off; + } + + location /api/ { + proxy_pass http://${HOST_ADMIN}/admin/api/; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_redirect off; + } + + location /admin/ { + proxy_pass http://${HOST_ADMIN}; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_redirect off; + } + + location /qa/ { + proxy_pass http://${HOST_QA}; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_redirect off; + } + + location = /events.json { + proxy_pass http://${HOST_ADMIN}/api/events/; + proxy_method GET; + proxy_pass_request_body off; + proxy_set_header Content-Length ""; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_redirect off; + proxy_cache STATIC; + proxy_cache_valid 3s; + } +}