diff --git a/.env.production.example b/.env.production.example index b56d734..1501ae9 100644 --- a/.env.production.example +++ b/.env.production.example @@ -1,19 +1,30 @@ -CONTAINER_NAME=universal-web -REVERSE_PROXY_NETWORK= -UPLOADS_VOLUME_NAME=universal_web_uploads +APP_DOMAIN=eshop.kompress.farmeris.sk -APP_HOST=https://eshop.example.com +APP_HOST=https://eshop.kompress.farmeris.sk PORT=5150 SERVER_BINDING=0.0.0.0 -DATABASE_URL= +POSTGRES_DB=kompress_eshop +POSTGRES_USER=kompress_eshop +POSTGRES_PASSWORD=change-me + JWT_SECRET= +JWT_EXPIRATION=604800 ADMIN_EMAIL= ADMIN_PASSWORD= ADMIN_NAME=Admin UPLOADS_ROOT=data/uploads +WORKER_MODE=BackgroundAsync + +DB_ENABLE_LOGGING=false +DB_CONNECT_TIMEOUT=500 +DB_IDLE_TIMEOUT=500 +DB_MIN_CONNECTIONS=1 +DB_MAX_CONNECTIONS=5 +DB_AUTO_MIGRATE=true + LOG_LEVEL=info LOG_FORMAT=compact @@ -24,3 +35,12 @@ SMTP_PORT=1025 SMTP_SECURE=false SMTP_USER= SMTP_PASSWORD= + +OAUTH_PRIVATE_KEY= +OAUTH_CLIENT_ID= +OAUTH_CLIENT_SECRET= +OAUTH_AUTH_URL=https://accounts.google.com/o/oauth2/auth +OAUTH_TOKEN_URL=https://www.googleapis.com/oauth2/v3/token +OAUTH_REDIRECT_URL=https://eshop.kompress.farmeris.sk/api/oauth2/google/callback/cookie +OAUTH_PROFILE_URL=https://openidconnect.googleapis.com/v1/userinfo +OAUTH_PROTECTED_URL=https://eshop.kompress.farmeris.sk/api/oauth2/protected diff --git a/Caddyfile b/Caddyfile index 4f67a47..c3c149e 100644 --- a/Caddyfile +++ b/Caddyfile @@ -1,5 +1,15 @@ -eshop.example.com { - encode gzip +http://{$APP_DOMAIN:eshop.kompress.farmeris.sk} { + redir https://{$APP_DOMAIN:eshop.kompress.farmeris.sk}{uri} permanent +} + +https://{$APP_DOMAIN:eshop.kompress.farmeris.sk} { + encode zstd gzip + + header { + Strict-Transport-Security "max-age=31536000" + X-Content-Type-Options "nosniff" + Referrer-Policy "strict-origin-when-cross-origin" + } @static path /static/* header @static Cache-Control "public, max-age=2592000" @@ -8,7 +18,3 @@ eshop.example.com { reverse_proxy kompress:5150 } - -eshop.example.com { - redir https://eshop.example.com{uri} permanent -} diff --git a/README.md b/README.md index 43b9bdd..e6edc2e 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,22 @@ listening on http://localhost:5150 You can check your [configuration](config/development.yaml) to pick either frontend setup or server-side rendered template, and activate the relevant configuration sections. +## Production Podman Deploy + +Create the production environment file: + +```sh +cp .env.production.example .env.production +``` + +Edit `.env.production` and set real secrets for `POSTGRES_PASSWORD`, `JWT_SECRET`, `OAUTH_PRIVATE_KEY`, and the OAuth client values. Then start the production stack: + +```sh +make up +``` + +The production Podman stack runs Caddy, the Loco app, and Postgres. Caddy publishes ports `80` and `443`; the app port `5150` stays private on the container network. HTTP requests on port `80` are redirected to HTTPS on port `443`. + ## Getting help diff --git a/podman-compose.prod.yml b/podman-compose.prod.yml index 6d4e89c..118d3cc 100644 --- a/podman-compose.prod.yml +++ b/podman-compose.prod.yml @@ -1,4 +1,22 @@ services: + caddy: + image: docker.io/library/caddy:2-alpine + container_name: kompress-caddy + env_file: + - .env.production + ports: + - "443:443" + - "443:443/udp" + volumes: + - ./Caddyfile:/etc/caddy/Caddyfile:ro + - caddy_data:/data + - caddy_config:/config + networks: + - kompress_eshop-net + restart: unless-stopped + depends_on: + - kompress + kompress: container_name: kompress build: @@ -6,11 +24,16 @@ services: dockerfile: Podmanfile env_file: - .env.production + environment: + DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB} volumes: - kompress_eshop_data:/usr/app/data networks: - kompress_eshop-net restart: unless-stopped + depends_on: + postgres: + condition: service_healthy healthcheck: test: ["CMD-SHELL", "curl -fsS http://localhost:5150/_ping"] interval: 30s @@ -18,11 +41,36 @@ services: retries: 3 start_period: 20s + postgres: + image: docker.io/library/postgres:16-alpine + container_name: kompress-postgres + env_file: + - .env.production + environment: + POSTGRES_DB: ${POSTGRES_DB} + POSTGRES_USER: ${POSTGRES_USER} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + volumes: + - postgres_data:/var/lib/postgresql/data + networks: + - kompress_eshop-net + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "pg_isready -U \"$${POSTGRES_USER}\" -d \"$${POSTGRES_DB}\""] + interval: 10s + timeout: 5s + retries: 5 + networks: kompress_eshop-net: - external: true + name: kompress_eshop-net volumes: kompress_eshop_data: - external: true name: kompress_eshop_data + postgres_data: + name: kompress_postgres_data + caddy_data: + name: kompress_caddy_data + caddy_config: + name: kompress_caddy_config