From a39f264776ae177dfd00eabeea115546696fcde5 Mon Sep 17 00:00:00 2001 From: Anton Hughes Date: Fri, 13 Dec 2024 17:44:55 +1300 Subject: [PATCH 01/20] Restrict egress on siren container --- .gitignore | 1 + Dockerfile | 2 +- docker-compose.yml | 36 ++++++++++++++++++++++++++++++++---- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 089e036e..e0d93a2f 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ certs npm-debug.log* yarn-debug.log* yarn-error.log* +/.yarn build-storybook.log diff --git a/Dockerfile b/Dockerfile index c586dd49..7363f8cd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -39,4 +39,4 @@ RUN rm /etc/nginx/sites-enabled/default; \ COPY --from=intermediate /app /app/ -ENTRYPOINT /app/docker-assets/docker-entrypoint.sh +ENTRYPOINT ["/app/docker-assets/docker-entrypoint.sh"] diff --git a/docker-compose.yml b/docker-compose.yml index 0447fa47..0e54be39 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,11 +1,39 @@ services: + nginx-proxy: + image: nginx:stable + networks: + - internet + - no_internet + volumes: + - ./docker-assets/nginx_proxy_google.conf.template:/etc/nginx/nginx.conf.template:ro + command: /bin/bash -c "envsubst '$$PROXY_TARGET' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf && nginx -g 'daemon off;'" + environment: + - PROXY_TARGET=65.108.39.206 + restart: always + siren: image: sigp/siren + networks: + - no_internet + tty: true + stdin_open: true + entrypoint: "/bin/bash" ports: - "4443:443" # comment this line when using `SSL_ENABLED=false` -# - "4080:80" # uncomment this line when using `SSL_ENABLED=false` + - "4080:80" # uncomment this line when using `SSL_ENABLED=false` env_file: - .env -# uncomment these 2 lines if you use docker on linux and want to use the special host `host.docker.internal` as your BN/VC address -# extra_hosts: -# - "host.docker.internal:host-gateway" + tmpfs: + - /tmp + environment: + - NODE_ENV=production + # Point to nginx-proxy for beacon/validator access + - BEACON_URL=http://nginx-proxy:9001 + - VALIDATOR_URL=http://nginx-proxy:9002 + +networks: + internet: + driver: bridge + no_internet: + driver: bridge + internal: true # Prevents direct internet access From fc6ae1a4f72f92c64793f86888f1d1236e1ba023 Mon Sep 17 00:00:00 2001 From: Anton Hughes Date: Mon, 16 Dec 2024 11:25:43 +1300 Subject: [PATCH 02/20] siren container w/ no internet --- .../nginx_proxy_google.conf.template | 75 +++++++++++++++++++ docker-assets/ssl-conf | 18 +++++ docker-compose.yml | 28 ++++--- 3 files changed, 111 insertions(+), 10 deletions(-) create mode 100644 docker-assets/nginx_proxy_google.conf.template create mode 100755 docker-assets/ssl-conf diff --git a/docker-assets/nginx_proxy_google.conf.template b/docker-assets/nginx_proxy_google.conf.template new file mode 100644 index 00000000..278f3eae --- /dev/null +++ b/docker-assets/nginx_proxy_google.conf.template @@ -0,0 +1,75 @@ +user nginx; +worker_processes 8; + +error_log /dev/stdout warn; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; +} + +# HTTP configuration for Siren web interface +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + 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; + access_log /dev/stdout main; + + sendfile on; + keepalive_timeout 65; + + # Resolve DNS for upstreams + resolver 127.0.0.11 ipv6=off; + + # Siren web interface proxy + server { + listen 4080; + server_name localhost; + + location / { + set $upstream_siren ${SIREN_HOST}; + proxy_pass http://$upstream_siren:80; + proxy_set_header Host $host; + 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 $scheme; + proxy_read_timeout 300; + proxy_connect_timeout 300; + } + } +} + +# TCP proxy configuration for beacon/validator +stream { + log_format main '$remote_addr - [$time_local] '; + access_log /var/log/nginx/access.log main; + access_log /dev/stdout main; + + # Beacon Node proxy + server { + listen 9001; + proxy_pass ${PROXY_TARGET}:9001; + } + + # Validator Client proxy + server { + listen 9002; + proxy_pass ${PROXY_TARGET}:9002; + } + + # Block all other outbound connections + server { + listen 80; + return 444; # Connection closed without response + } + + server { + listen 443; + return 444; # Connection closed without response + } +} diff --git a/docker-assets/ssl-conf b/docker-assets/ssl-conf new file mode 100755 index 00000000..68e589e7 --- /dev/null +++ b/docker-assets/ssl-conf @@ -0,0 +1,18 @@ +ssl on; +ssl_session_timeout 5m; +ssl_protocols TLSv1.2 TLSv1.1 TLSv1; +ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK'; +ssl_prefer_server_ciphers on; + +ssl_dhparam /etc/ssl/private/dhparam2048.pem; + +# Enable HSTS (17280000s = 200 days) +add_header Strict-Transport-Security max-age=17280000; + +# Enable OCSP stapling +ssl_stapling on; +ssl_stapling_verify on; +resolver 8.8.4.4; + +# Enable SSL session cache +ssl_session_cache shared:SSL:10m; diff --git a/docker-compose.yml b/docker-compose.yml index 0e54be39..0f89e756 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,39 +1,47 @@ services: nginx-proxy: + container_name: nginx-proxy image: nginx:stable networks: - internet - no_internet + ports: + - "4080:4080" # For Siren web interface + - "9001:9001" # For beacon node + - "9002:9002" # For validator volumes: - ./docker-assets/nginx_proxy_google.conf.template:/etc/nginx/nginx.conf.template:ro - command: /bin/bash -c "envsubst '$$PROXY_TARGET' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf && nginx -g 'daemon off;'" + command: /bin/bash -c "envsubst '$$PROXY_TARGET $$SIREN_HOST' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf && nginx -g 'daemon off;'" environment: - PROXY_TARGET=65.108.39.206 + - SIREN_HOST=siren restart: always siren: + container_name: siren image: sigp/siren networks: - - no_internet - tty: true - stdin_open: true - entrypoint: "/bin/bash" - ports: - - "4443:443" # comment this line when using `SSL_ENABLED=false` - - "4080:80" # uncomment this line when using `SSL_ENABLED=false` + - no_internet # Only on internal network + expose: + - "80" env_file: - .env tmpfs: - /tmp environment: - NODE_ENV=production - # Point to nginx-proxy for beacon/validator access - BEACON_URL=http://nginx-proxy:9001 - VALIDATOR_URL=http://nginx-proxy:9002 + - SSL_ENABLED=false + - PORT=3000 + - BACKEND_URL=http://127.0.0.1:3001 + restart: always networks: internet: + name: internet driver: bridge no_internet: + name: no_internet driver: bridge - internal: true # Prevents direct internet access + internal: true # Prevents direct internet access From ff3abc81c53043b619cd9c46515ed42f71f58416 Mon Sep 17 00:00:00 2001 From: Anton Hughes Date: Mon, 16 Dec 2024 12:15:05 +1300 Subject: [PATCH 03/20] Enhance security and stability of docker-compose configuration - Change restart policy to 'unless-stopped' - Restrict permissions on tmp and run mounts - Add security options to prevent privilege escalation - Implement health checks for the siren service - Enable network encryption for the no_internet network --- docker-compose.yml | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 0f89e756..ecd2421c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,6 +2,8 @@ services: nginx-proxy: container_name: nginx-proxy image: nginx:stable + # Run nginx as non-root user + # user: nginx networks: - internet - no_internet @@ -15,19 +17,21 @@ services: environment: - PROXY_TARGET=65.108.39.206 - SIREN_HOST=siren - restart: always + + restart: unless-stopped # Don't restart if manually stopped siren: container_name: siren image: sigp/siren networks: - - no_internet # Only on internal network + - no_internet # Only on internal network expose: - "80" env_file: - .env tmpfs: - - /tmp + - /tmp:noexec,nosuid # Mount tmp with restricted permissions + - /run:noexec,nosuid # Required for nginx pid file environment: - NODE_ENV=production - BEACON_URL=http://nginx-proxy:9001 @@ -35,7 +39,17 @@ services: - SSL_ENABLED=false - PORT=3000 - BACKEND_URL=http://127.0.0.1:3001 - restart: always + # Security enhancements + security_opt: + - no-new-privileges:true # Prevent privilege escalation + + healthcheck: # Add health monitoring + test: ["CMD", "curl", "-f", "http://localhost:3000"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + restart: unless-stopped # Don't restart if manually stopped networks: internet: @@ -44,4 +58,7 @@ networks: no_internet: name: no_internet driver: bridge - internal: true # Prevents direct internet access + internal: true # Prevents direct internet access + # # Enable network encryption + driver_opts: + encrypted: "true" From 7a111b0968faa27706b5c0eee3538091279262a1 Mon Sep 17 00:00:00 2001 From: Anton Hughes Date: Mon, 16 Dec 2024 12:26:57 +1300 Subject: [PATCH 04/20] Update docker-compose to include BN_TARGET and VC_TARGET environment variables --- docker-compose.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index ecd2421c..36535b2e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -13,10 +13,10 @@ services: - "9002:9002" # For validator volumes: - ./docker-assets/nginx_proxy_google.conf.template:/etc/nginx/nginx.conf.template:ro - command: /bin/bash -c "envsubst '$$PROXY_TARGET $$SIREN_HOST' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf && nginx -g 'daemon off;'" + command: /bin/bash -c "envsubst '$$BN_TARGET $$VC_TARGET $$SIREN_HOST' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf && nginx -g 'daemon off;'" environment: - - PROXY_TARGET=65.108.39.206 - - SIREN_HOST=siren + - BN_TARGET=65.108.39.206 + - VC_TARGET=65.108.39.206 restart: unless-stopped # Don't restart if manually stopped From f032c1e94760d28f40919c73c22d93bbbed7d778 Mon Sep 17 00:00:00 2001 From: Anton Hughes Date: Mon, 16 Dec 2024 12:27:06 +1300 Subject: [PATCH 05/20] Update nginx proxy configuration to use BN_TARGET and VC_TARGET variables --- docker-assets/nginx_proxy_google.conf.template | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker-assets/nginx_proxy_google.conf.template b/docker-assets/nginx_proxy_google.conf.template index 278f3eae..1e63cbd6 100644 --- a/docker-assets/nginx_proxy_google.conf.template +++ b/docker-assets/nginx_proxy_google.conf.template @@ -32,7 +32,7 @@ http { server_name localhost; location / { - set $upstream_siren ${SIREN_HOST}; + set $upstream_siren siren; proxy_pass http://$upstream_siren:80; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; @@ -53,13 +53,13 @@ stream { # Beacon Node proxy server { listen 9001; - proxy_pass ${PROXY_TARGET}:9001; + proxy_pass ${BN_TARGET}:9001; } # Validator Client proxy server { listen 9002; - proxy_pass ${PROXY_TARGET}:9002; + proxy_pass ${VC_TARGET}:9002; } # Block all other outbound connections From d0b9b21ddd94393556acede7f1a2dee6e50b7927 Mon Sep 17 00:00:00 2001 From: Anton Hughes Date: Mon, 16 Dec 2024 12:31:57 +1300 Subject: [PATCH 06/20] Remove non-root user configuration from nginx-proxy service in docker-compose --- docker-compose.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 36535b2e..ee368684 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,8 +2,6 @@ services: nginx-proxy: container_name: nginx-proxy image: nginx:stable - # Run nginx as non-root user - # user: nginx networks: - internet - no_internet From e61f51f0857760fd09cb87fc3e92660e918fc6d6 Mon Sep 17 00:00:00 2001 From: Anton Hughes Date: Mon, 16 Dec 2024 12:45:53 +1300 Subject: [PATCH 07/20] Refactor nginx proxy configuration to use upstream blocks for BN_TARGET and VC_TARGET --- docker-assets/nginx_proxy_google.conf.template | 14 ++++++++++++-- docker-compose.yml | 4 ++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/docker-assets/nginx_proxy_google.conf.template b/docker-assets/nginx_proxy_google.conf.template index 1e63cbd6..56e12a14 100644 --- a/docker-assets/nginx_proxy_google.conf.template +++ b/docker-assets/nginx_proxy_google.conf.template @@ -50,16 +50,26 @@ stream { access_log /var/log/nginx/access.log main; access_log /dev/stdout main; + # Split BN_TARGET into host and port using shell parameter expansion + upstream beacon_node { + server ${BN_TARGET}; + } + + # Split VC_TARGET into host and port using shell parameter expansion + upstream validator_client { + server ${VC_TARGET}; + } + # Beacon Node proxy server { listen 9001; - proxy_pass ${BN_TARGET}:9001; + proxy_pass beacon_node; } # Validator Client proxy server { listen 9002; - proxy_pass ${VC_TARGET}:9002; + proxy_pass validator_client; } # Block all other outbound connections diff --git a/docker-compose.yml b/docker-compose.yml index ee368684..4e1b752b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -13,8 +13,8 @@ services: - ./docker-assets/nginx_proxy_google.conf.template:/etc/nginx/nginx.conf.template:ro command: /bin/bash -c "envsubst '$$BN_TARGET $$VC_TARGET $$SIREN_HOST' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf && nginx -g 'daemon off;'" environment: - - BN_TARGET=65.108.39.206 - - VC_TARGET=65.108.39.206 + - BN_TARGET=65.108.39.206:9001 + - VC_TARGET=65.108.39.206:9002 restart: unless-stopped # Don't restart if manually stopped From e15cf879913ed36a7f087a1339e8d297e89dde68 Mon Sep 17 00:00:00 2001 From: Anton Hughes Date: Mon, 16 Dec 2024 13:24:47 +1300 Subject: [PATCH 08/20] Update nginx proxy configuration file path in docker-compose --- ...inx_proxy_google.conf.template => nginx_proxy.conf.template} | 0 docker-compose.yml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename docker-assets/{nginx_proxy_google.conf.template => nginx_proxy.conf.template} (100%) diff --git a/docker-assets/nginx_proxy_google.conf.template b/docker-assets/nginx_proxy.conf.template similarity index 100% rename from docker-assets/nginx_proxy_google.conf.template rename to docker-assets/nginx_proxy.conf.template diff --git a/docker-compose.yml b/docker-compose.yml index 4e1b752b..6842d337 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,7 +10,7 @@ services: - "9001:9001" # For beacon node - "9002:9002" # For validator volumes: - - ./docker-assets/nginx_proxy_google.conf.template:/etc/nginx/nginx.conf.template:ro + - ./docker-assets/nginx_proxy.conf.template:/etc/nginx/nginx.conf.template:ro command: /bin/bash -c "envsubst '$$BN_TARGET $$VC_TARGET $$SIREN_HOST' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf && nginx -g 'daemon off;'" environment: - BN_TARGET=65.108.39.206:9001 From 3d228107c7ab9c26fc27793712b108738e45546b Mon Sep 17 00:00:00 2001 From: Anton Hughes Date: Mon, 16 Dec 2024 14:21:39 +1300 Subject: [PATCH 09/20] Update BN_TARGET and VC_TARGET environment variables to use placeholder IPs --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 6842d337..adf3962f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -13,8 +13,8 @@ services: - ./docker-assets/nginx_proxy.conf.template:/etc/nginx/nginx.conf.template:ro command: /bin/bash -c "envsubst '$$BN_TARGET $$VC_TARGET $$SIREN_HOST' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf && nginx -g 'daemon off;'" environment: - - BN_TARGET=65.108.39.206:9001 - - VC_TARGET=65.108.39.206:9002 + - BN_TARGET=your-BN-ip:9001 + - VC_TARGET=your-VC-ip:9002 restart: unless-stopped # Don't restart if manually stopped From 0fa9a88522c2afcbb10232751ad065938ec3f050 Mon Sep 17 00:00:00 2001 From: Anton Hughes Date: Mon, 16 Dec 2024 14:21:56 +1300 Subject: [PATCH 10/20] Update README to include BN_TARGET and VC_TARGET configuration instructions --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 89e2233f..507ad5d1 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,16 @@ developers. Specifically the [Lighthouse UI](https://lighthouse-book.sigmaprime. Docker is the recommended way to run Siren. This will expose Siren as a webapp. -Configuration is done through environment variables, the best way to get started is by copying `.env.example` to `.env` and editing the relevant sections (typically, this would at least include `BEACON_URL`, `VALIDATOR_URL` and `API_TOKEN`) +Configuration is done through environment variables, the best way to get started is by copying `.env.example` to `.env` and editing the relevant sections (typically, this would at least include `BEACON_URL`, `VALIDATOR_URL` and `API_TOKEN`). + +You will also need to set the Beacon and Validator ip and port in the docker compose file: + +```yml + + environment: + - BN_TARGET=your-BN-ip:9001 + - VC_TARGET=your-VC-ip:9002 +``` Then to run the image: From 910e64e9a0b4ab61b5ee8cbc16299d0b8304d472 Mon Sep 17 00:00:00 2001 From: Anton Hughes Date: Mon, 16 Dec 2024 15:39:25 +1300 Subject: [PATCH 11/20] Update docker-compose to configure SSL and use environment variables for BN_TARGET and VC_TARGET --- docker-compose.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index adf3962f..efe4d863 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,14 +7,13 @@ services: - no_internet ports: - "4080:4080" # For Siren web interface - - "9001:9001" # For beacon node - - "9002:9002" # For validator + - "4443:443" # For Siren web interface with SSL volumes: - ./docker-assets/nginx_proxy.conf.template:/etc/nginx/nginx.conf.template:ro - command: /bin/bash -c "envsubst '$$BN_TARGET $$VC_TARGET $$SIREN_HOST' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf && nginx -g 'daemon off;'" - environment: - - BN_TARGET=your-BN-ip:9001 - - VC_TARGET=your-VC-ip:9002 + command: /bin/bash -c "export BN_TARGET=$(echo $BEACON_URL | awk -F'[/:]' '{print $4 \":\" $5}') && export VC_TARGET=$(echo $VALIDATOR_URL | awk -F'[/:]' '{print $4 \":\" $5}') && envsubst '$$BN_TARGET $$VC_TARGET $$SIREN_HOST' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf && nginx -g 'daemon off;'" + env_file: + - .env + restart: unless-stopped # Don't restart if manually stopped From 45b78c5a7ef4b7f2b1dad1b0d2e61e376ae7d1eb Mon Sep 17 00:00:00 2001 From: Anton Hughes Date: Mon, 16 Dec 2024 15:39:36 +1300 Subject: [PATCH 12/20] Update README to remove outdated BN_TARGET and VC_TARGET configuration instructions --- README.md | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/README.md b/README.md index 507ad5d1..9a7b7799 100644 --- a/README.md +++ b/README.md @@ -25,18 +25,10 @@ Docker is the recommended way to run Siren. This will expose Siren as a webapp. Configuration is done through environment variables, the best way to get started is by copying `.env.example` to `.env` and editing the relevant sections (typically, this would at least include `BEACON_URL`, `VALIDATOR_URL` and `API_TOKEN`). -You will also need to set the Beacon and Validator ip and port in the docker compose file: - -```yml - - environment: - - BN_TARGET=your-BN-ip:9001 - - VC_TARGET=your-VC-ip:9002 -``` Then to run the image: -`docker compose up` +`docker compose up` and visit `http://localhost:4080/dashboard` or `docker run --rm -ti --name siren -p 3443:443 --env-file $PWD/.env sigp/siren` From 69224d18aaf1dbe64224e8135369772534b6eeaa Mon Sep 17 00:00:00 2001 From: antondlr Date: Mon, 16 Dec 2024 14:01:24 +0100 Subject: [PATCH 13/20] switch to alpine-based nginx container --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index efe4d863..66541033 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ services: nginx-proxy: container_name: nginx-proxy - image: nginx:stable + image: nginx:alpine networks: - internet - no_internet From efef6d5ee1a9548d2579148e3be1d238e77235b0 Mon Sep 17 00:00:00 2001 From: antondlr Date: Mon, 16 Dec 2024 14:02:18 +0100 Subject: [PATCH 14/20] dont expose port 80, containers in same network can access regardless --- docker-compose.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 66541033..9f4a7006 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,8 +22,6 @@ services: image: sigp/siren networks: - no_internet # Only on internal network - expose: - - "80" env_file: - .env tmpfs: From 104f01074b48e2af53478eb8ad2228d9ca271462 Mon Sep 17 00:00:00 2001 From: antondlr Date: Mon, 16 Dec 2024 14:08:56 +0100 Subject: [PATCH 15/20] update ssl config --- docker-assets/ssl-conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-assets/ssl-conf b/docker-assets/ssl-conf index 68e589e7..d09eb70e 100755 --- a/docker-assets/ssl-conf +++ b/docker-assets/ssl-conf @@ -1,7 +1,7 @@ ssl on; ssl_session_timeout 5m; -ssl_protocols TLSv1.2 TLSv1.1 TLSv1; -ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK'; +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 on; ssl_dhparam /etc/ssl/private/dhparam2048.pem; From 58757e3d05e79ecafc9d9db13cdc75a8151daa4f Mon Sep 17 00:00:00 2001 From: Anton Hughes Date: Tue, 17 Dec 2024 10:11:43 +1300 Subject: [PATCH 16/20] Update README to reflect correct URL --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9a7b7799..31e52e15 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Configuration is done through environment variables, the best way to get started Then to run the image: -`docker compose up` and visit `http://localhost:4080/dashboard` +`docker compose up` and visit `http://localhost:4080/` or `docker run --rm -ti --name siren -p 3443:443 --env-file $PWD/.env sigp/siren` From 190ecd622fb3a1b7d8925afa56b8260631f0955d Mon Sep 17 00:00:00 2001 From: Anton Hughes Date: Tue, 17 Dec 2024 11:46:35 +1300 Subject: [PATCH 17/20] [Alpine] Change command in docker-compose to use /bin/sh instead of /bin/bash --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 9f4a7006..de78af7e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,7 +10,7 @@ services: - "4443:443" # For Siren web interface with SSL volumes: - ./docker-assets/nginx_proxy.conf.template:/etc/nginx/nginx.conf.template:ro - command: /bin/bash -c "export BN_TARGET=$(echo $BEACON_URL | awk -F'[/:]' '{print $4 \":\" $5}') && export VC_TARGET=$(echo $VALIDATOR_URL | awk -F'[/:]' '{print $4 \":\" $5}') && envsubst '$$BN_TARGET $$VC_TARGET $$SIREN_HOST' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf && nginx -g 'daemon off;'" + command: /bin/sh -c "export BN_TARGET=$(echo $BEACON_URL | awk -F'[/:]' '{print $4 \":\" $5}') && export VC_TARGET=$(echo $VALIDATOR_URL | awk -F'[/:]' '{print $4 \":\" $5}') && envsubst '$$BN_TARGET $$VC_TARGET $$SIREN_HOST' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf && nginx -g 'daemon off;'" env_file: - .env From 40ef91eecd6c292fafcc2e52c30e7a0ec5f5cf25 Mon Sep 17 00:00:00 2001 From: Anton Hughes Date: Tue, 17 Dec 2024 11:47:00 +1300 Subject: [PATCH 18/20] Add DNS resolver configuration for beacon node and validator client proxies --- docker-assets/nginx_proxy.conf.template | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docker-assets/nginx_proxy.conf.template b/docker-assets/nginx_proxy.conf.template index 56e12a14..24a178f7 100644 --- a/docker-assets/nginx_proxy.conf.template +++ b/docker-assets/nginx_proxy.conf.template @@ -63,12 +63,20 @@ stream { # Beacon Node proxy server { listen 9001; + # Resolve DNS for upstreams + resolver 127.0.0.11; + + # Proxy pass to the beacon node proxy_pass beacon_node; } # Validator Client proxy server { listen 9002; + # Resolve DNS for upstreams + resolver 127.0.0.11; + + # Proxy pass to the validator client proxy_pass validator_client; } From c9b515f6f872de9ca6cf9930233c9fb80f1c2454 Mon Sep 17 00:00:00 2001 From: Anton Hughes Date: Wed, 18 Dec 2024 15:43:37 +1300 Subject: [PATCH 19/20] Add SSL certificate generation and update docker-compose for cert-init service --- docker-assets/generate-certs.sh | 17 ++++++++++++++++ docker-compose.yml | 36 ++++++++++++++++++++++++++------- 2 files changed, 46 insertions(+), 7 deletions(-) create mode 100755 docker-assets/generate-certs.sh diff --git a/docker-assets/generate-certs.sh b/docker-assets/generate-certs.sh new file mode 100755 index 00000000..b7750245 --- /dev/null +++ b/docker-assets/generate-certs.sh @@ -0,0 +1,17 @@ +#!/bin/sh +set -e + +# Create directory for certificates if it doesn't exist +mkdir -p /etc/nginx/certs + +# Generate self-signed certificate and private key +openssl req -x509 -nodes -days 365 -newkey rsa:4096 \ + -keyout /etc/nginx/certs/nginx.key \ + -out /etc/nginx/certs/nginx.crt \ + -subj "/C=AU/CN=siren/emailAddress=noreply@sigmaprime.io" + +# Set proper permissions +chmod 600 /etc/nginx/certs/nginx.key +chmod 644 /etc/nginx/certs/nginx.crt + +echo "SSL certificates generated successfully" diff --git a/docker-compose.yml b/docker-compose.yml index de78af7e..15d2cf19 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,19 @@ services: + cert-init: + container_name: cert-init + image: alpine/openssl:3.3.2 + command: /usr/local/bin/generate-certs.sh + volumes: + - ./docker-assets/generate-certs.sh:/usr/local/bin/generate-certs.sh + - nginx-certs:/etc/nginx/certs + entrypoint: > + /bin/sh -c " + # Make script executable + chmod +x /usr/local/bin/generate-certs.sh && + # Run script + /usr/local/bin/generate-certs.sh + " + nginx-proxy: container_name: nginx-proxy image: nginx:alpine @@ -6,15 +21,17 @@ services: - internet - no_internet ports: - - "4080:4080" # For Siren web interface - - "4443:443" # For Siren web interface with SSL + - "4080:4080" # For Siren web interface HTTP + - "4443:4443" # For Siren web interface HTTPS (fixed port mapping) volumes: - ./docker-assets/nginx_proxy.conf.template:/etc/nginx/nginx.conf.template:ro + - nginx-certs:/etc/nginx/certs:ro command: /bin/sh -c "export BN_TARGET=$(echo $BEACON_URL | awk -F'[/:]' '{print $4 \":\" $5}') && export VC_TARGET=$(echo $VALIDATOR_URL | awk -F'[/:]' '{print $4 \":\" $5}') && envsubst '$$BN_TARGET $$VC_TARGET $$SIREN_HOST' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf && nginx -g 'daemon off;'" env_file: - .env - - + depends_on: + cert-init: + condition: service_completed_successfully restart: unless-stopped # Don't restart if manually stopped siren: @@ -31,13 +48,14 @@ services: - NODE_ENV=production - BEACON_URL=http://nginx-proxy:9001 - VALIDATOR_URL=http://nginx-proxy:9002 - - SSL_ENABLED=false + - SSL_ENABLED=true - PORT=3000 - BACKEND_URL=http://127.0.0.1:3001 # Security enhancements security_opt: - no-new-privileges:true # Prevent privilege escalation - + depends_on: + - nginx-proxy healthcheck: # Add health monitoring test: ["CMD", "curl", "-f", "http://localhost:3000"] interval: 30s @@ -54,6 +72,10 @@ networks: name: no_internet driver: bridge internal: true # Prevents direct internet access - # # Enable network encryption + # Enable network encryption driver_opts: encrypted: "true" + +volumes: + nginx-certs: + driver: local From 01dd14075e0a5d3dced2cddfeb31835a351f5011 Mon Sep 17 00:00:00 2001 From: Anton Hughes Date: Wed, 18 Dec 2024 16:10:58 +1300 Subject: [PATCH 20/20] Update README with Docker Compose usage instructions and SSL access notes --- README.md | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 31e52e15..cd985970 100644 --- a/README.md +++ b/README.md @@ -25,16 +25,47 @@ Docker is the recommended way to run Siren. This will expose Siren as a webapp. Configuration is done through environment variables, the best way to get started is by copying `.env.example` to `.env` and editing the relevant sections (typically, this would at least include `BEACON_URL`, `VALIDATOR_URL` and `API_TOKEN`). +#### Starting Siren with Docker Compose -Then to run the image: +1. Copy the environment file: + ```bash + cp .env.example .env + ``` -`docker compose up` and visit `http://localhost:4080/` -or +2. Edit `.env` with your configuration (at minimum set `BEACON_URL`, `VALIDATOR_URL`, and `API_TOKEN`) + +3. Start the services: + ```bash + docker compose up -d + ``` + The `-d` flag runs the containers in the background. Remove it if you want to see the logs directly in your terminal. + +4. Access Siren at https://localhost:4443 + + Note: When you first visit the site, your browser will show a security warning because Siren uses a self-signed SSL certificate. This is expected and safe for local development. You can proceed by: + - In Chrome: Click "Advanced" and then "Proceed to localhost (unsafe)" + - In Firefox: Click "Advanced..." and then "Accept the Risk and Continue" + - In Safari: Click "Show Details" and then "visit this website" + +#### Stopping Siren + +To stop the services: +```bash +docker compose down +``` + +To stop and remove all data (including certificates): +```bash +docker compose down -v +``` + +#### Alternative Docker Run Method + +You can also run Siren using the docker run command: `docker run --rm -ti --name siren -p 3443:443 --env-file $PWD/.env sigp/siren` This will open port 3443 and allow your browser to connect. - To start Siren, visit `https://localhost:3443` in your web browser (ignore the certificate warning). Advanced users can mount their own certificate (the config expects 3 files: `/certs/cert.pem` `/certs/key.pem` `/certs/key.pass`) @@ -57,4 +88,4 @@ Navigate to the backend directory `cd backend`. Install all required Node packag #### Build and run the frontend After initializing the backend, return to the root directory. Install all frontend dependencies by executing `yarn`. Build the frontend using `yarn build`. Start the frontend production server with `yarn start`. -This will allow you to access siren at `http://localhost:3000` by default. +This will allow you to access siren at `http://localhost:3000` by default.