diff --git a/docs/guides/selfhosting/index.mdx b/docs/guides/selfhosting/index.mdx
index 13280ce1..b2141e3a 100644
--- a/docs/guides/selfhosting/index.mdx
+++ b/docs/guides/selfhosting/index.mdx
@@ -36,116 +36,162 @@ Add two files with the names `docker-compose.yml` and `.env`. Paste their conten
```yaml
-
# This file is a minimal plug and play working example of a runnable OpenShock stack.
-
services:
-db: # We need a postgres database, preferably version 15+
-image: postgres:17
-restart: unless-stopped
-container_name: openshock-postgres
-healthcheck:
-test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
-start_period: 20s
-interval: 30s
-retries: 5
-timeout: 5s
-networks: - openshock
-environment:
-POSTGRES_PASSWORD: ${PG_PASS:?database password required}
-POSTGRES_USER: ${PG_USER:-openshock}
-POSTGRES_DB: ${PG_DB:-openshock}
-volumes: - ./postgres-data:/var/lib/postgresql/data # Data is saved in a folder called postgres-data in the current working directory
-
-redis:
-restart: unless-stopped
-networks: - openshock
-image: redis/redis-stack-server:latest
-healthcheck:
-test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
-start_period: 20s
-interval: 30s
-retries: 5
-timeout: 3s
-volumes: - ./redis-data:/data # Same goes for redis
-environment: - "REDIS_ARGS=--notify-keyspace-events KEA"
-
-api:
-image: ghcr.io/openshock/api:latest
-restart: unless-stopped
-networks: - openshock
-depends_on: - db - redis
-env_file: .env
-environment:
-OPENSHOCK**FRONTEND**BASEURL: https://${OPENSHOCK_DOMAIN:-openshock.local}
+ db: # We need a postgres database, preferably version 15+
+ image: postgres:17
+ restart: unless-stopped
+ container_name: openshock-postgres
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
+ start_period: 20s
+ interval: 30s
+ retries: 5
+ timeout: 5s
+ networks:
+ - openshock
+ environment:
+ POSTGRES_PASSWORD: ${PG_PASS:?database password required}
+ POSTGRES_USER: ${PG_USER:-openshock}
+ POSTGRES_DB: ${PG_DB:-openshock}
+ volumes:
+ - ./postgres-data:/var/lib/postgresql/data # Data is saved in a folder called postgres-data in the current working directory
+
+ redis:
+ restart: unless-stopped
+ networks:
+ - openshock
+ image: redis/redis-stack-server:latest
+ healthcheck:
+ test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
+ start_period: 20s
+ interval: 30s
+ retries: 5
+ timeout: 3s
+ volumes:
+ - ./redis-data:/data # Same goes for redis
+ environment:
+ - "REDIS_ARGS=--notify-keyspace-events KEA"
+
+ api:
+ image: ghcr.io/openshock/api:latest
+ restart: unless-stopped
+ networks:
+ - openshock
+ depends_on:
+ - db
+ - redis
+ env_file: .env
+ environment:
+ OPENSHOCK__FRONTEND__BASEURL: https://${OPENSHOCK_DOMAIN:-openshock.local}
OPENSHOCK__FRONTEND__SHORTURL: https://${OPENSHOCK_DOMAIN:-openshock.local}
-OPENSHOCK**FRONTEND**COOKIEDOMAIN: ${OPENSHOCK_DOMAIN:-openshock.local}
+ OPENSHOCK__FRONTEND__COOKIEDOMAIN: ${OPENSHOCK_DOMAIN:-openshock.local}
OPENSHOCK__DB__CONN: Host=db;Port=5432;Database=${PG_USER:-openshock};Username=${PG_USER:-openshock};Password=${PG_PASS}
-OPENSHOCK**REDIS**HOST: redis
-OPENSHOCK**TURNSTILE**ENABLE: false
-labels: - "traefik.enable=true" - "traefik.http.routers.openshock-api.rule=Host(`${OPENSHOCK_API_SUBDOMAIN:-api}.${OPENSHOCK_DOMAIN:-openshock.local}`)" - "traefik.http.routers.openshock-api.entrypoints=https" - "traefik.http.routers.openshock-api.tls=true" - "traefik.http.routers.openshock-api.service=openshock-api" - "traefik.http.services.openshock-api.loadbalancer.server.port=80"
-
-webui:
-image: ghcr.io/openshock/webui:latest
-restart: unless-stopped
-networks: - openshock
-environment:
-OPENSHOCK_NAME: OpenShock
-OPENSHOCK_URL: ${OPENSHOCK_DOMAIN:-openshock.local}
+ OPENSHOCK__REDIS__HOST: redis
+ OPENSHOCK__TURNSTILE__ENABLE: false
+ OPENSHOCK__ACCOUNT__REGISTRATIONENABLED: true
+ labels:
+ - "traefik.enable=true"
+ - "traefik.http.routers.openshock-api.rule=Host(`${OPENSHOCK_API_SUBDOMAIN:-api}.${OPENSHOCK_DOMAIN:-openshock.local}`)"
+ - "traefik.http.routers.openshock-api.entrypoints=https"
+ - "traefik.http.routers.openshock-api.tls=true"
+ - "traefik.http.routers.openshock-api.service=openshock-api"
+ - "traefik.http.services.openshock-api.loadbalancer.server.port=80"
+
+ webui:
+ image: ghcr.io/openshock/webui:latest
+ restart: unless-stopped
+ networks:
+ - openshock
+ environment:
+ OPENSHOCK_NAME: OpenShock
+ OPENSHOCK_URL: ${OPENSHOCK_DOMAIN:-openshock.local}
OPENSHOCK_SHARE_URL: https://${OPENSHOCK_DOMAIN:-openshock.local}
-OPENSHOCK_API_URL: https://${OPENSHOCK_API_SUBDOMAIN:-api}.${OPENSHOCK_DOMAIN:-openshock.local}
-labels: - "traefik.enable=true" - "traefik.http.routers.openshock-webui.rule=Host(`${OPENSHOCK_DOMAIN:-openshock.local}`)" - "traefik.http.routers.openshock-webui.entrypoints=https" - "traefik.http.routers.openshock-webui.tls=true" - "traefik.http.routers.openshock-webui.service=openshock-webui" - "traefik.http.routers.openshock-webui.middlewares=osr-s,osr-c,osr-t" - "traefik.http.services.openshock-webui.loadbalancer.server.port=80" - "traefik.http.middlewares.osr-s.redirectregex.regex=^https://${OPENSHOCK_DOMAIN:-openshock.local}/s/(.*)"
+ OPENSHOCK_API_URL: https://${OPENSHOCK_API_SUBDOMAIN:-api}.${OPENSHOCK_DOMAIN:-openshock.local}
+ labels:
+ - "traefik.enable=true"
+ - "traefik.http.routers.openshock-webui.rule=Host(`${OPENSHOCK_DOMAIN:-openshock.local}`)"
+ - "traefik.http.routers.openshock-webui.entrypoints=https"
+ - "traefik.http.routers.openshock-webui.tls=true"
+ - "traefik.http.routers.openshock-webui.service=openshock-webui"
+ - "traefik.http.routers.openshock-webui.middlewares=osr-s,osr-c,osr-t"
+ - "traefik.http.services.openshock-webui.loadbalancer.server.port=80"
+ - "traefik.http.middlewares.osr-s.redirectregex.regex=^https://${OPENSHOCK_DOMAIN:-openshock.local}/s/(.*)"
- "traefik.http.middlewares.osr-s.redirectregex.replacement=https://${OPENSHOCK_DOMAIN:-openshock.local}/#/public/proxy/shares/links/$$1"
- "traefik.http.middlewares.osr-c.redirectregex.regex=^https://${OPENSHOCK_DOMAIN:-openshock.local}/c/(.*)"
- - "traefik.http.middlewares.osr-c.redirectregex.replacement=https://${OPENSHOCK_DOMAIN:-openshock.local}/#/public/proxy/shares/code/$$1" - "traefik.http.middlewares.osr-t.redirectregex.regex=^https://${OPENSHOCK_DOMAIN:-openshock.local}/t/(.*)"
+ - "traefik.http.middlewares.osr-c.redirectregex.replacement=https://${OPENSHOCK_DOMAIN:-openshock.local}/#/public/proxy/shares/code/$$1"
+ - "traefik.http.middlewares.osr-t.redirectregex.regex=^https://${OPENSHOCK_DOMAIN:-openshock.local}/t/(.*)"
- "traefik.http.middlewares.osr-t.redirectregex.replacement=https://${OPENSHOCK_DOMAIN:-openshock.local}/#/public/proxy/token/$$1"
-lcg:
-image: ghcr.io/openshock/live-control-gateway:latest
-restart: unless-stopped
-networks: - openshock
-depends_on: - db - redis
-environment:
-OPENSHOCK**REDIS**HOST: redis
-OPENSHOCK**DB**CONN: Host=db;Port=5432;Database=${PG_USER:-openshock};Username=${PG_USER:-openshock};Password=${PG_PASS}
+ lcg:
+ image: ghcr.io/openshock/live-control-gateway:latest
+ restart: unless-stopped
+ networks:
+ - openshock
+ depends_on:
+ - db
+ - redis
+ environment:
+ OPENSHOCK__REDIS__HOST: redis
+ OPENSHOCK__DB__CONN: Host=db;Port=5432;Database=${PG_USER:-openshock};Username=${PG_USER:-openshock};Password=${PG_PASS}
OPENSHOCK__LCG__COUNTRYCODE: DE
OPENSHOCK__LCG__FQDN: ${OPENSHOCK_GATEWAY_SUBDOMAIN:-gateway}.${OPENSHOCK_DOMAIN:-openshock.local}
-labels: - "traefik.enable=true" - "traefik.http.routers.openshock-gateway.rule=Host(`${OPENSHOCK_GATEWAY_SUBDOMAIN:-gateway}.${OPENSHOCK_DOMAIN:-openshock.local}`)" - "traefik.http.routers.openshock-gateway.entrypoints=https" - "traefik.http.routers.openshock-gateway.tls=true" - "traefik.http.routers.openshock-gateway.service=openshock-gateway" - "traefik.http.services.openshock-gateway.loadbalancer.server.port=80"
-
-cron:
-image: ghcr.io/openshock/cron:latest
-restart: unless-stopped
-networks: - openshock
-depends_on: - db - redis
-environment:
-OPENSHOCK**REDIS**HOST: redis
-OPENSHOCK**DB**CONN: Host=db;Port=5432;Database=${PG_USER:-openshock};Username=${PG_USER:-openshock};Password=${PG_PASS}
labels:
- "traefik.enable=true"
- - "traefik.http.routers.openshock-cron.rule=Host(`${OPENSHOCK_DOMAIN:-localhost}`) && PathPrefix(`/hangfire`)" - "traefik.http.routers.openshock-cron.entrypoints=https" - "traefik.http.routers.openshock-cron.tls=true" - "traefik.http.routers.openshock-cron.service=openshock-cron" - "traefik.http.services.openshock-cron.loadbalancer.server.port=780"
-
-traefik:
-image: traefik:latest
-container_name: traefik
-command:
-#- "--log.level=DEBUG" - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entryPoints.https.address=:443"
-#- "--api.insecure=true"
-restart: unless-stopped
-networks: - openshock
-ports: - 80:80 - 443:443
-#- 8080:8080 # Traefik Web UI (enabled by --api.insecure=true)
-volumes: - /etc/localtime:/etc/localtime:ro - /var/run/docker.sock:/var/run/docker.sock:ro
+ - "traefik.http.routers.openshock-gateway.rule=Host(`${OPENSHOCK_GATEWAY_SUBDOMAIN:-gateway}.${OPENSHOCK_DOMAIN:-openshock.local}`)"
+ - "traefik.http.routers.openshock-gateway.entrypoints=https"
+ - "traefik.http.routers.openshock-gateway.tls=true"
+ - "traefik.http.routers.openshock-gateway.service=openshock-gateway"
+ - "traefik.http.services.openshock-gateway.loadbalancer.server.port=80"
+
+ cron:
+ image: ghcr.io/openshock/cron:latest
+ restart: unless-stopped
+ networks:
+ - openshock
+ depends_on:
+ - db
+ - redis
+ environment:
+ OPENSHOCK__REDIS__HOST: redis
+ OPENSHOCK__DB__CONN: Host=db;Port=5432;Database=${PG_USER:-openshock};Username=${PG_USER:-openshock};Password=${PG_PASS}
+ labels:
+ - "traefik.enable=true"
+ - "traefik.http.routers.openshock-cron.rule=Host(`${OPENSHOCK_DOMAIN:-localhost}`) && PathPrefix(`/hangfire`)"
+ - "traefik.http.routers.openshock-cron.entrypoints=https"
+ - "traefik.http.routers.openshock-cron.tls=true"
+ - "traefik.http.routers.openshock-cron.service=openshock-cron"
+ - "traefik.http.services.openshock-cron.loadbalancer.server.port=780"
+
+ traefik:
+ image: traefik:latest
+ container_name: traefik
+ command:
+ #- "--log.level=DEBUG"
+ - "--providers.docker=true"
+ - "--providers.docker.exposedbydefault=false"
+ - "--entryPoints.https.address=:443"
+ #- "--api.insecure=true"
+ restart: unless-stopped
+ networks:
+ - openshock
+ ports:
+ - 80:80
+ - 443:443
+ #- 8080:8080 # Traefik Web UI (enabled by --api.insecure=true)
+ volumes:
+ - /etc/localtime:/etc/localtime:ro
+ - /var/run/docker.sock:/var/run/docker.sock:ro
networks:
-openshock:
-
-````
+ openshock:
+```
-``` yaml
+```yaml
# Required variables (uncomment and set values!)
#PG_PASS=someSecurePassword(1)
@@ -173,8 +219,7 @@ OPENSHOCK__MAIL__SMTP__USERNAME=open@shock.zap
OPENSHOCK__MAIL__SMTP__PASSWORD=SMTPPASSWORD
OPENSHOCK__MAIL__SMTP__ENABLESSL=true
OPENSHOCK__MAIL__SMTP__VERIFYCERTIFICATE=true
-
-````
+```
1. Primary postgres database password. Make it something secure like a random 32 character password.
2. Application domain. e.g. `openshock.app`
@@ -218,104 +263,121 @@ In addition we also need a ssl certificate, change the path to your needs, and c
```yaml
-
# Minimal example for nginx
-
services:
-db: # We need a postgres database, preferably version 15+
-image: postgres:16
-restart: unless-stopped
-container_name: openshock-postgres
-healthcheck:
-test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
-start_period: 20s
-interval: 30s
-retries: 5
-timeout: 5s
-networks: - openshock
-environment:
-POSTGRES_PASSWORD: ${PG_PASS:?database password required}
-POSTGRES_USER: ${PG_USER:-openshock}
-POSTGRES_DB: ${PG_DB:-openshock}
-volumes: - ./postgres-data:/var/lib/postgresql/data # Data is saved in a folder called postgres-data in the current working directory
-
-redis:
-restart: unless-stopped
-networks: - openshock
-image: redis/redis-stack-server:latest
-healthcheck:
-test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
-start_period: 20s
-interval: 30s
-retries: 5
-timeout: 3s
-volumes: - ./redis-data:/data # Same goes for redis
-environment: - "REDIS_ARGS=--notify-keyspace-events KEA"
-
-api:
-image: ghcr.io/openshock/api:latest
-restart: unless-stopped
-networks: - openshock
-depends_on: - db - redis
-env_file: .env
-environment:
-OPENSHOCK**FRONTEND**BASEURL: https://${OPENSHOCK_DOMAIN:-openshock.local}
+ db: # We need a postgres database, preferably version 15+
+ image: postgres:16
+ restart: unless-stopped
+ container_name: openshock-postgres
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
+ start_period: 20s
+ interval: 30s
+ retries: 5
+ timeout: 5s
+ networks:
+ - openshock
+ environment:
+ POSTGRES_PASSWORD: ${PG_PASS:?database password required}
+ POSTGRES_USER: ${PG_USER:-openshock}
+ POSTGRES_DB: ${PG_DB:-openshock}
+ volumes:
+ - ./postgres-data:/var/lib/postgresql/data # Data is saved in a folder called postgres-data in the current working directory
+
+ redis:
+ restart: unless-stopped
+ networks:
+ - openshock
+ image: redis/redis-stack-server:latest
+ healthcheck:
+ test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
+ start_period: 20s
+ interval: 30s
+ retries: 5
+ timeout: 3s
+ volumes:
+ - ./redis-data:/data # Same goes for redis
+ environment:
+ - "REDIS_ARGS=--notify-keyspace-events KEA"
+
+ api:
+ image: ghcr.io/openshock/api:latest
+ restart: unless-stopped
+ networks:
+ - openshock
+ depends_on:
+ - db
+ - redis
+ env_file: .env
+ environment:
+ OPENSHOCK__FRONTEND__BASEURL: https://${OPENSHOCK_DOMAIN:-openshock.local}
OPENSHOCK__FRONTEND__SHORTURL: https://${OPENSHOCK_DOMAIN:-openshock.local}
-OPENSHOCK**FRONTEND**COOKIEDOMAIN: ${OPENSHOCK_DOMAIN:-openshock.local}
+ OPENSHOCK__FRONTEND__COOKIEDOMAIN: ${OPENSHOCK_DOMAIN:-openshock.local}
OPENSHOCK__DB__CONN: Host=db;Port=5432;Database=${PG_USER:-openshock};Username=${PG_USER:-openshock};Password=${PG_PASS}
-OPENSHOCK**REDIS**HOST: redis
-OPENSHOCK**TURNSTILE**ENABLE: false
-
-webui:
-image: ghcr.io/openshock/webui:latest
-restart: unless-stopped
-networks: - openshock
-environment:
-OPENSHOCK_NAME: OpenShock
-OPENSHOCK_URL: ${OPENSHOCK_DOMAIN:-openshock.local}
+ OPENSHOCK__REDIS__HOST: redis
+ OPENSHOCK__TURNSTILE__ENABLE: false
+ OPENSHOCK__ACCOUNT__REGISTRATIONENABLED: true
+
+ webui:
+ image: ghcr.io/openshock/webui:latest
+ restart: unless-stopped
+ networks:
+ - openshock
+ environment:
+ OPENSHOCK_NAME: OpenShock
+ OPENSHOCK_URL: ${OPENSHOCK_DOMAIN:-openshock.local}
OPENSHOCK_SHARE_URL: https://${OPENSHOCK_DOMAIN:-openshock.local}
-OPENSHOCK_API_URL: https://${OPENSHOCK_API_SUBDOMAIN:-api}.${OPENSHOCK_DOMAIN:-openshock.local}
-
-lcg:
-image: ghcr.io/openshock/live-control-gateway:latest
-restart: unless-stopped
-networks: - openshock
-depends_on: - db - redis
-environment:
-OPENSHOCK**REDIS**HOST: redis
-OPENSHOCK**DB**CONN: Host=db;Port=5432;Database=${PG_USER:-openshock};Username=${PG_USER:-openshock};Password=${PG_PASS}
+ OPENSHOCK_API_URL: https://${OPENSHOCK_API_SUBDOMAIN:-api}.${OPENSHOCK_DOMAIN:-openshock.local}
+
+ lcg:
+ image: ghcr.io/openshock/live-control-gateway:latest
+ restart: unless-stopped
+ networks:
+ - openshock
+ depends_on:
+ - db
+ - redis
+ environment:
+ OPENSHOCK__REDIS__HOST: redis
+ OPENSHOCK__DB__CONN: Host=db;Port=5432;Database=${PG_USER:-openshock};Username=${PG_USER:-openshock};Password=${PG_PASS}
OPENSHOCK__LCG__COUNTRYCODE: DE
OPENSHOCK__LCG__FQDN: ${OPENSHOCK_GATEWAY_SUBDOMAIN:-gateway}.${OPENSHOCK_DOMAIN:-openshock.local}
-cron:
-image: ghcr.io/openshock/cron:master
-restart: unless-stopped
-networks: - openshock
-depends_on: - db - redis
-environment:
-OPENSHOCK**REDIS**HOST: redis
-OPENSHOCK**DB**CONN: Host=db;Port=5432;Database=${PG_USER:-openshock};Username=${PG_USER:-openshock};Password=${PG_PASS}
-
-nginx:
-image: nginx
-restart: unless-stopped
-networks: - openshock
-ports: - 80:80 - 443:443
-volumes: - ./nginx-site.conf:/etc/nginx/conf.d/nginx-site.conf - ./certs:/certs
+ cron:
+ image: ghcr.io/openshock/cron:master
+ restart: unless-stopped
+ networks:
+ - openshock
+ depends_on:
+ - db
+ - redis
+ environment:
+ OPENSHOCK__REDIS__HOST: redis
+ OPENSHOCK__DB__CONN: Host=db;Port=5432;Database=${PG_USER:-openshock};Username=${PG_USER:-openshock};Password=${PG_PASS}
-networks:
-openshock:
+ nginx:
+ image: nginx
+ restart: unless-stopped
+ networks:
+ - openshock
+ ports:
+ - 80:80
+ - 443:443
+ volumes:
+ - ./nginx-site.conf:/etc/nginx/conf.d/nginx-site.conf
+ - ./certs:/certs
-````
+networks:
+ openshock:
+```
**You will need to change the server names here!**
-```yaml
-
+```nginx
server {
listen 443 ssl;
server_name openshock.local;
@@ -373,11 +435,21 @@ server {
proxy_set_header Connection $connection_upgrade
}
}
-
-````
+```
+
+## Creating your admin account
+
+A fresh instance has **no admin user**. You can bootstrap the first admin with an SQL update.
+
+```bash
+docker exec -it openshock-postgres \
+ psql -U openshock -d openshock \
+ -c "UPDATE users SET roles = array_append(roles, 'admin') WHERE email = 'you@example.com';"
+```
+
## Done
Congratulations, the backend and website should be working now. :partying_face: