Ipv6 support (#1437)

* Ipv6 support

* Proper fix for containers, dev and local

* Edits similar to non-AI compose file

---------

Co-authored-by: Juan José Mata <jjmata@jjmata.com>
This commit is contained in:
soky srm
2026-04-13 13:44:37 +02:00
committed by GitHub
parent 0761e8c237
commit 90b1308866
6 changed files with 54 additions and 2 deletions

View File

@@ -5,7 +5,9 @@ x-db-env: &db_env
x-rails-env: &rails_env
DB_HOST: db
HOST: "0.0.0.0"
# Bind the dev server to all interfaces inside the container so Docker's
# published port reaches it from the host. Rails reads BINDING natively.
BINDING: "0.0.0.0"
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
BUNDLE_PATH: /bundle

View File

@@ -1,3 +1,3 @@
web: bundle exec ${DEBUG:+rdbg -O -n -c --} bin/rails server -b 0.0.0.0
web: bundle exec ${DEBUG:+rdbg -O -n -c --} bin/rails server
css: bundle exec bin/rails tailwindcss:watch 2>/dev/null
worker: bundle exec sidekiq

View File

@@ -255,10 +255,16 @@ services:
# bypassing Pipelock's MCP scanning (auth token is still required).
# For hardened deployments, use `expose: [3000]` instead and front
# the web UI with a separate reverse proxy.
#
# To also publish on IPv6 (dual-stack), uncomment the line below AND
# set BINDING=:: in the environment block. See docs/hosting/docker.md
# "Binding to IPv6" for details.
# - "[::]:${PORT:-3000}:3000"
- ${PORT:-3000}:3000
restart: unless-stopped
environment:
<<: *rails_env
# BINDING: "::" # Uncomment for IPv6 dual-stack inside the container
depends_on:
db:
condition: service_healthy

View File

@@ -66,9 +66,14 @@ services:
- app-storage:/rails/storage
ports:
- ${PORT:-3000}:3000
# To also publish on IPv6 (dual-stack), uncomment the line below AND
# set BINDING=:: in the environment block. See docs/hosting/docker.md
# "Binding to IPv6" for details.
# - "[::]:${PORT:-3000}:3000"
restart: unless-stopped
environment:
<<: *rails_env
# BINDING: "::" # Uncomment for IPv6 dual-stack inside the container
depends_on:
db:
condition: service_healthy

View File

@@ -39,6 +39,8 @@ if rails_env == "production"
end
# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
# The bind host is controlled via the Rails-native `BINDING` env var (set to
# `0.0.0.0` in containers, or `::` for IPv6 dual-stack). See docs/hosting/docker.md.
port ENV.fetch("PORT") { 3000 }
# Specifies the `environment` that Puma will run in.

View File

@@ -111,6 +111,43 @@ and change it to `true`
RAILS_ASSUME_SSL: "true"
```
#### Binding to IPv6 (optional)
By default Sure listens on `0.0.0.0:3000` (IPv4 wildcard) inside the container and Docker publishes the port on the host's IPv4 interface only. If you want the app reachable over IPv6 as well, two things need to change:
1. **Tell the app to bind to `[::]`** by setting `BINDING=::` in the container environment. `BINDING` is Rails' native env var for the server bind address. On any kernel with `net.ipv6.bindv6only=0` (the default on Linux and macOS) a single `[::]` bind is **dual-stack**: it accepts both IPv6 and IPv4 clients from the same socket. You do not need two binds and you do not need two ports.
2. **Tell Docker to publish the host port on IPv6** by adding a bracketed-host `ports:` entry alongside the existing IPv4 one.
In `compose.yml`:
```yaml
services:
web:
ports:
- ${PORT:-3000}:3000
- "[::]:${PORT:-3000}:3000"
environment:
<<: *rails_env
BINDING: "::"
```
With both changes in place, `http://127.0.0.1:3000/` and `http://[::1]:3000/` both work against the same container.
**Note:** Docker's default userland proxy already bridges host-side IPv6 publishes to the container's internal IPv4 address, so in many setups just adding the `[::]:` port entry is enough. Setting `BINDING=::` inside the container only becomes load-bearing when the Docker daemon has `"ipv6": true` + `"ip6tables": true` configured (uncommon for self-hosters) and forwards raw IPv6 packets into the container via netfilter instead of the proxy. Setting both is harmless and future-proof.
If you are running behind a reverse proxy that terminates TLS, nothing else changes — `proxy_pass http://[::1]:3000` and `proxy_pass http://127.0.0.1:3000` both work because the `[::]` bind is dual-stack.
#### Local development bind
For `bin/dev` on your own machine, the server now defaults to Rails' native `localhost` bind (`127.0.0.1` + `[::1]`) — only reachable from the same machine. If you need external access (phone on the same WiFi, devcontainer port forwarding, LAN testing), set the Rails-native env var:
```bash
BINDING=0.0.0.0 bin/dev # reachable from LAN
BINDING=:: bin/dev # IPv6 dual-stack
```
The bundled devcontainer at `.devcontainer/docker-compose.yml` already pins `BINDING: "0.0.0.0"` so Docker port forwarding reaches the app — no manual override needed when using the devcontainer.
### Step 4: Run the app
You are now ready to run the app. Start with the following command to make sure everything is working: