Coder running on Laravel Forge can not connect to Websocket endpoint - docker

I've configured Coder and followed this instructions to set it up via Docker Compose.
In order to be able to use a public domain, I've configured a reverse proxy with nginx. Everything works except for the websocket connection which is used to get logs, status updates etc etc.
The error is: wss://workspaces.mydomain.io/api/private/workspaces/623ae5f6-0e4817996a28f4e5e592cb87/watch-stats' failed
The server is managed via Laravel Forge.
Here is my docker-compose.yml:
version: "3.5"
services:
coder:
image: docker.io/codercom/coder:1.28.2
container_name: coderd
restart: unless-stopped
ports:
- 7080:7080/tcp
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ${HOME}/.coder:/var/run/coder
environment:
DEVURL_HOST: "*.workspaces.mydomain.io"
And here my nginx configuration:
server {
listen 80;
listen [::]:80;
server_name .workspaces.mydomain.io;
server_tokens off;
root /home/forge/workspaces.mydomain.io/coder/public;
# FORGE SSL (DO NOT REMOVE!)
# ssl_certificate;
# ssl_certificate_key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_dhparam /etc/nginx/dhparams.pem;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.html index.htm index.php;
charset utf-8;
# FORGE CONFIG (DO NOT REMOVE!)
include forge-conf/workspaces.mydomain.io/server/*;
location / {
proxy_pass http://127.0.0.1:7080;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
access_log off;
error_log /var/log/nginx/workspaces.mydomain.io-error.log error;
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}

Related

ngnix with letsencrypt with client_max_body_size attribure for nexus

my nginx proxy generates the following entry for my nexus:
# nexus.myhost.de
upstream nexus.myhost.de {
## Can be connected with "frontproxy_default" network
# nexus
server 172.23.0.13:8081;
}
server {
server_name nexus.myhost.de;
listen 80 ;
access_log /var/log/nginx/access.log vhost;
# Do not HTTPS redirect Let'sEncrypt ACME challenge
location ^~ /.well-known/acme-challenge/ {
auth_basic off;
auth_request off;
allow all;
root /usr/share/nginx/html;
try_files $uri =404;
break;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
server_name nexus.myhost.de;
listen 443 ssl http2 ;
access_log /var/log/nginx/access.log vhost;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_certificate /etc/nginx/certs/nexus.myhost.de.crt;
ssl_certificate_key /etc/nginx/certs/nexus.myhost.de.key;
ssl_dhparam /etc/nginx/certs/nexus.myhost.de.dhparam.pem;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/certs/nexus.myhost.de.chain.pem;
add_header Strict-Transport-Security "max-age=31536000" always;
include /etc/nginx/vhost.d/default;
location / {
proxy_pass http://nexus.myhost.de;
}
}
For this I am using these Images:
image: jwilder/nginx-proxy
image: jrcs/letsencrypt-nginx-proxy-companion
From here
https://help.sonatype.com/repomanager3/planning-your-implementation/run-behind-a-reverse-proxy?_ga=2.13238647.112157402.1655493796-115056297.1650880144
I know that I need client_max_body_size in the configuration.
But the configuration file is generated permanently. So how can I keep the automatic updates from letsencrypt and add this parameter to this single configuration?

Nginx reverse proxy is loading different sites when refreshing

I want to host multiple websites in one server with nginx reverse proxy by following this tutorial
https://www.datanovia.com/en/lessons/how-host-multiple-https-websites-on-one-server/
The Nginx proxy and each website are launched separately with Docker.
But every time I reload one of the website, it load the content of other website. For example:
Load websiteone.tk 1st time, loaded website ONE's content.
Refresh websiteone.tk , loaded website TWO's content
Refresh websiteone.tk again, loaded website THREE's content
Load websitetwo.tk 1st time, loaded website TWO content
Refresh websitetwo.tk , loaded website THREE content.
I am a beginner for both nginx and docker. I can't tell if the problem happens in nginx or docker. May anyone please kindly advise? Thank you very much.
The nginx-proxy default.conf is
map $http_x_forwarded_proto $proxy_x_forwarded_proto { default $http_x_forwarded_proto;
'' $scheme;
}
map $http_x_forwarded_port $proxy_x_forwarded_port {
default $http_x_forwarded_port;
'' $server_port;
}
map $http_upgrade $proxy_connection {
default upgrade;
'' close;
}
server_names_hash_bucket_size 128;
map $proxy_x_forwarded_proto $proxy_x_forwarded_ssl {
default off;
https on;
}
gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss t>log_format vhost '$host $remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$upstream_addr"';
access_log off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA3> ssl_prefer_server_ciphers off;
error_log /dev/stderr;
# HTTP 1.1 support
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $proxy_connection;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
proxy_set_header X-Original-URI $request_uri;
# Mitigate httpoxy attack (see README for details)
proxy_set_header Proxy "";
server {
server_name _; # This is just an invalid value which will never trigger on a real hostname.
server_tokens off;
listen 80;
access_log /var/log/nginx/access.log vhost;
return 503;
}
server {
server_name _; # This is just an invalid value which will never trigger on a real hostname.
server_tokens off;
listen 443 ssl http2;
access_log /var/log/nginx/access.log vhost;
return 503;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_certificate /etc/nginx/certs/default.crt;
ssl_certificate_key /etc/nginx/certs/default.key;
}
# websiteone.tk
upstream websiteone.tk {
## Can be connected with "nginx-proxy" network
# websiteonetk_my-app_1
server 192.168.32.8:80;
}
server {
server_name websiteone.tk;
listen 80 ;
access_log /var/log/nginx/access.log vhost;
# Do not HTTPS redirect Let'sEncrypt ACME challenge
location ^~ /.well-known/acme-challenge/ {
auth_basic off;
auth_request off;
allow all;
root /usr/share/nginx/html;
try_files $uri =404;
break;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
server_name websiteone.tk;
listen 443 ssl http2 ;
access_log /var/log/nginx/access.log vhost;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_certificate /etc/nginx/certs/websiteone.tk.crt;
ssl_certificate_key /etc/nginx/certs/websiteone.tk.key;
ssl_dhparam /etc/nginx/certs/websiteone.tk.dhparam.pem;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/certs/websiteone.tk.chain.pem;
add_header Strict-Transport-Security "max-age=31536000" always;
include /etc/nginx/vhost.d/default;
location / {
proxy_pass http://websiteone.tk;
}
}
# websitetwo.tk
upstream websitetwo.tk {
## Can be connected with "nginx-proxy" network
# websitetwotk_my-app_1
server 192.168.32.13:80;
}
server {
server_name websitetwo.tk;
listen 80 ;
access_log /var/log/nginx/access.log vhost;
# Do not HTTPS redirect Let'sEncrypt ACME challenge
location ^~ /.well-known/acme-challenge/ {
auth_basic off;
auth_request off;
allow all;
root /usr/share/nginx/html;
try_files $uri =404;
break;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
server_name websitetwo.tk;
listen 443 ssl http2 ;
access_log /var/log/nginx/access.log vhost;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_certificate /etc/nginx/certs/websitetwo.tk.crt;
ssl_certificate_key /etc/nginx/certs/websitetwo.tk.key;
ssl_dhparam /etc/nginx/certs/websitetwo.tk.dhparam.pem;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/certs/websitetwo.tk.chain.pem;
add_header Strict-Transport-Security "max-age=31536000" always;
include /etc/nginx/vhost.d/default;
location / {
proxy_pass http://websitetwo.tk;
}
}
# websitethree.tk
upstream websitethree.tk {
## Can be connected with "nginx-proxy" network
# websitethreetk_my-app_1
server 192.168.32.3:80;
}
server {
server_name websitethree.tk;
listen 80 ;
access_log /var/log/nginx/access.log vhost;
# Do not HTTPS redirect Let'sEncrypt ACME challenge
location ^~ /.well-known/acme-challenge/ {
auth_basic off;
auth_request off;
allow all;
root /usr/share/nginx/html;
try_files $uri =404;
break;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
server_name websitethree.tk;
listen 443 ssl http2 ;
access_log /var/log/nginx/access.log vhost;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_certificate /etc/nginx/certs/websitethree.tk.crt;
ssl_certificate_key /etc/nginx/certs/websitethree.tk.key;
ssl_dhparam /etc/nginx/certs/websitethree.tk.dhparam.pem;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/certs/websitethree.tk.chain.pem;
add_header Strict-Transport-Security "max-age=31536000" always;
include /etc/nginx/vhost.d/default;
location / {
proxy_pass http://websitethree.tk;
}
}
The docker-compose for the nginx proxy is
version: '3.6'
services:
nginx:
image: nginx
labels:
com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy: "true"
container_name: nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./conf.d:/etc/nginx/conf.d
- ./vhost.d:/etc/nginx/vhost.d
- ./html:/usr/share/nginx/html
- ./certs:/etc/nginx/certs:ro
nginx-gen:
image: jwilder/docker-gen
command: -notify-sighup nginx -watch -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
container_name: nginx-gen
restart: unless-stopped
volumes:
- ./conf.d:/etc/nginx/conf.d
- ./vhost.d:/etc/nginx/vhost.d
- ./html:/usr/share/nginx/html
- ./certs:/etc/nginx/certs:ro
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro
nginx-letsencrypt:
image: jrcs/letsencrypt-nginx-proxy-companion
container_name: nginx-letsencrypt
restart: unless-stopped
volumes:
- ./conf.d:/etc/nginx/conf.d
- ./vhost.d:/etc/nginx/vhost.d
- ./html:/usr/share/nginx/html
- ./certs:/etc/nginx/certs:rw
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
NGINX_DOCKER_GEN_CONTAINER: "nginx-gen"
NGINX_PROXY_CONTAINER: "nginx"
networks:
default:
external:
name: nginx-proxy
The nginx default.conf for one of the website is
server {
root /application2;
index index.php;
location ~ \.php$ {
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PHP_VALUE "error_log=/var/log/nginx/application_php_errors.log";
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
include fastcgi_params;
}
}
The docker-compose/yml for one of the website is below.
Websiteone working directory is /application1.
Websitetwo working directory is /application2. etc
version: '3.1'
services:
my-app:
image: 'nginx:alpine'
volumes:
- '.:/application2'
- './phpdocker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf'
restart: always
environment:
- VIRTUAL_HOST=websitetwo.tk
- VIRTUAL_PORT=80
- LETSENCRYPT_HOST=websitetwo.tk
expose:
- 80
mailhog:
image: 'mailhog/mailhog:latest'
ports:
- '21001:8025'
php-fpm:
build: phpdocker/php-fpm
working_dir: /application2
volumes:
- '.:/application2'
- './phpdocker/php-fpm/php-ini-overrides.ini:/etc/php/8.1/fpm/conf.d/99-overrides.ini'
networks:
default:
external:
name: nginx-proxy

Serve via containerized Nginx files from php-fpm container?

My app files are located in phpfpm container and I need to serve them through nginx. I want to avoid mounting the same files in two containers, so I'm trying to figure out a way to serve them only from one, phpfpm, container. When I use reverse proxy to other containers:
server {
listen 0.0.0.0:8080;
server_name myapp.test;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HOST $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://phpfpm:900;
proxy_redirect off;
}
}
I get 502 Bad Gateway error with the following error log record:
1 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 172.18.0.1, server: myapp.test, request: "GET / HTTP/1.1", upstream: "http://172.18.0.2:9000/", host: "myapp.test"
I guess it's because phpfpm container is not a HTTP server.
So, alternatively, I try using fastcgi_pass like so:
server {
listen 0.0.0.0:8080;
server_name myapp.test;
root /app;
location / {
try_files $uri $uri/index.php;
}
location ~ \.php$ {
fastcgi_pass phpfpm:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
}
This serves *.php files as expected, but doesn't serve other files, namely static content.
How do I makenginx serve both .php and static files from my phpfpm container?
Here's my docker-compose.yml:
version: "3.7"
services:
phpfpm:
image: "php-fpm:7.3"
volumes:
- ./site:/app
ports:
- "9000:9000"
nginx:
image: "nginx:1.17"
volumes:
- ./nginx/app.conf:/opt/nginx/conf/nginx.conf
ports:
- "80:8080"
You have 2 issues:
You did not mount your static content into your Nginx container, therefore it cannot be served. Add this volume to your container
./site/public/:/var/www/html/public/:ro
You need to setup your Nginx config in order to serve this static content. You may try this one
server {
listen 0.0.0.0:8080;
server_name myapp.test;
root /var/www/html/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.html index.htm index.php;
charset utf-8;
location / {
try_files $uri /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass phpfpm:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi.conf;
}
}

Nginx refuses connections to flask app, flask app without nginx works fine

I have 2 docker containers deployed using docker compose.
One is nginx and the other is my flask application. I am only using nginx as a static server for let's encrypt certification.
If I deploy my flask app without nginx, I can successfully curl / ping my server. However, the moment nginx is introduced, I am not able to connect.
What I want to do is at least access my server via numeric external ip e.g. xx.xx.xx.xx and then my domain which points to the same ip. (My domain is actually a subdomain e.g. api.domain.com)
My docker compose is:
services:
nginx:
build:
context: ./nginx
dockerfile: Dockerfile
args:
DOMAIN: ${DOMAIN}
FLASK: application
ports:
- 80:80
- 443:443
volumes:
- /etc/letsencrypt:/etc/letsencrypt
depends_on:
- application
application:
build:
context: ./flask_app
dockerfile: Dockerfile
ports:
- 5000:5000
nginx.conf
user nginx;
worker_processes auto;
worker_rlimit_nofile 8192;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
charset utf-8;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
server_tokens off;
log_not_found off;
types_hash_max_size 2048;
client_max_body_size 16M;
include mime.types;
default_type application/octet-stream;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ecdh_curve X25519:sect571r1:secp521r1:secp384r1;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_ciphers 'TLS13+AESGCM+AES128:TLS13+AESGCM+AES256:TLS13+CHACHA20:EECDH+AESGCM:EECDH+CHACHA20';
ssl_stapling on;
ssl_stapling_verify on;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
include conf.d/*.conf;
}
flask_app.conf
server {
listen 80;
listen [::]:80;
server_name www.${DOMAIN} ${DOMAIN};
location ^~ /.well-known/acme-challenge/ {
root /var/www/_letsencrypt;
}
location / {
return 301 https://${DOMAIN}${DOLLAR}request_uri;
}
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name www.${DOMAIN} ${DOMAIN};
ssl_certificate /etc/letsencrypt/live/${DOMAIN}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${DOMAIN}/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/${DOMAIN}/chain.pem;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
# You might want to change the CSP policy to fit your needs - see https://content-security-policy.com/
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self';";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header Allow "GET, POST, HEAD" always;
access_log /var/log/nginx/${DOMAIN}.access.log;
error_log /var/log/nginx/${DOMAIN}.error.log warn;
location / {
proxy_http_version 1.1;
proxy_cache_bypass ${DOLLAR}http_upgrade;
proxy_hide_header X-Powered-By;
proxy_hide_header Server;
proxy_hide_header X-AspNetMvc-Version;
proxy_hide_header X-AspNet-Version;
proxy_set_header Proxy "";
proxy_set_header Upgrade ${DOLLAR}http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host ${DOLLAR}host;
proxy_set_header X-Real-IP ${DOLLAR}remote_addr;
proxy_set_header X-Forwarded-For ${DOLLAR}proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto ${DOLLAR}scheme;
proxy_set_header X-Forwarded-Host ${DOLLAR}host;
proxy_set_header X-Forwarded-Port ${DOLLAR}server_port;
proxy_pass http://application:5000;
}
location ~* \.(?:css|cur|js|jpe?g|gif|htc|ico|png|html|xml|otf|ttf|eot|woff|woff2|svg)${DOLLAR} {
expires 7d;
add_header Pragma public;
add_header Cache-Control public;
proxy_pass http://application:5000;
}
if ( ${DOLLAR}request_method !~ ^(GET|POST|HEAD)${DOLLAR} ) {
return 405;
}
if (${DOLLAR}http_user_agent ~* LWP::Simple|BBBike|wget) {
return 403;
}
location ~ /\.(?!well-known) {
deny all;
}
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;
}
I'm not sure why your nginx config contains ${DOLLAR} in multiple places. I don't think this is valid syntax, and can't find any documentation relating to this. Lines like:
proxy_set_header Host ${DOLLAR}host;
Should actually be:
proxy_set_header Host $host;
As for using ${DOMAIN} in the nginx conf, I would avoid this and opt for a more simple configuration. Just specify the domain in the nginx config file:
server_name www.example.com example.com;
I'd familiarise yourself with the official nginx image docs under "Complex configuration" it shows you how to copy a working config out of a running container, then modify this to your needs.
Once you have this working, if you really want to specify the domain in your docker-compose file, and treat your nginx config as a template which is modified at container-start time, you could proceed to read the section "Using environment variables in nginx configuration" which shows a workaround to use envsubst to acehive this. This is probably not required for single site deployments however.

Encrypting R Plumber API using Let's Encrypt and Docker

I’m trying to host an API on AWS EC2 running ubuntu and the communication need to be through HTTPS
I’m building the code in R and using Plumber to create an API and build a docker image
First I build the image:
docker build github.com/eaoestergaard/UNPIE -t eaoestergaard/unpie
And then run the image on port 8001
docker run -d -p 8001:8000 --name unpie1 eaoestergaard/unpie
Then I follow this (awesome) guide in order to set up nginx with Let's Encrypt and Certbot, but substitute the production site with my API
My docker-compose.yml look like this
version: '3.1'
services:
production-nginx-container:
container_name: 'production-nginx-container'
image: nginx:latest
ports:
- "80:80"
- "443:443"
volumes:
- ./production.conf:/etc/nginx/conf.d/default.conf
- ./production-site:/usr/share/nginx/html
- ./dh-param/dhparam-2048.pem:/etc/ssl/certs/dhparam-2048.pem
- /docker-volumes/etc/letsencrypt/live/example.com/fullchain.pem:/etc/letsencrypt/live/example.com/fullchain.pem
- /docker-volumes/etc/letsencrypt/live/example.com/privkey.pem:/etc/letsencrypt/live/example.com/privkey.pem
networks:
- docker-network
depends_on:
- unpie1
unpie1:
image: eaoestergaard/unpie
restart: always
ports:
- "7001:8000"
networks:
docker-network:
driver: bridge
And my Nginx configuration file production.conf
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
location ^~ /.well-known/acme-challenge {
root /usr/share/nginx/html;
default_type text/plain;
allow all;
}
location / {
rewrite ^ https://$host$request_uri? permanent;
}
}
#https://example.com
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_buffer_size 8k;
ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
ssl_ecdh_curve secp384r1;
ssl_session_tickets off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8;
location ^~ /.well-known/acme-challenge {
root /usr/share/nginx/html;
default_type text/plain;
allow all;
}
location /unpie1/ {
proxy_pass http://unpie1:8000/;
proxy_set_header Host $host;
}
return 301 https://www.example.com$request_uri;
}
#https://www.example.com
server {
server_name www.example.com;
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_tokens off;
ssl on;
ssl_buffer_size 8k;
ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
ssl_ecdh_curve secp384r1;
ssl_session_tickets off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location ^~ /.well-known/acme-challenge {
root /usr/share/nginx/html;
default_type text/plain;
allow all;
}
location / {
#security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
#CSP
add_header Content-Security-Policy "frame-src 'self'; default-src 'self'; script-src 'self' 'unsafe-inline' https://maxcdn.bootstrapcdn.com https://ajax.googleapis.com; img-src 'self'; style-src 'self' https://maxcdn.bootstrapcdn.com; font-src 'self' data: https://maxcdn.bootstrapcdn.com; form-action 'self'; upgrade-insecure-requests;" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
}
root /usr/share/nginx/html;
index index.html;
}
Both created with inspiration from the plumber documentation section 7.4.2
Then spin up the docker container
cd /docker/letsencrypt-docker-nginx/src/production
sudo docker-compose up -d
I can connect to the API at http (eg http://example.com:7001/fv.annuity), but unfortunately not at https - I suspect my configuration files to be incomplete, but as I'm new into this it's not clear to me what I'm missing.

Resources