From 41179116b896ddf8000cc7a4a23ae25f76877789 Mon Sep 17 00:00:00 2001 From: Anty Date: Wed, 17 Jun 2026 20:35:05 +0200 Subject: [PATCH 1/3] fix: reformat selfhosting guide --- docs/guides/selfhosting/index.mdx | 410 +++++++++++++++++------------- 1 file changed, 235 insertions(+), 175 deletions(-) diff --git a/docs/guides/selfhosting/index.mdx b/docs/guides/selfhosting/index.mdx index 13280ce1..de627705 100644 --- a/docs/guides/selfhosting/index.mdx +++ b/docs/guides/selfhosting/index.mdx @@ -36,116 +36,161 @@ 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 + 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 +218,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 +262,120 @@ 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 + + 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 +433,11 @@ server { proxy_set_header Connection $connection_upgrade } } - -```` +``` + ## Done Congratulations, the backend and website should be working now. :partying_face: From 17500927fad6c904b20aa60f2466fa226afd2805 Mon Sep 17 00:00:00 2001 From: Anty Date: Wed, 17 Jun 2026 20:35:28 +0200 Subject: [PATCH 2/3] feat: add OPENSHOCK__ACCOUNT__REGISTRATIONENABLED env option --- docs/guides/selfhosting/index.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/guides/selfhosting/index.mdx b/docs/guides/selfhosting/index.mdx index de627705..2100f649 100644 --- a/docs/guides/selfhosting/index.mdx +++ b/docs/guides/selfhosting/index.mdx @@ -90,6 +90,7 @@ services: 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 + OPENSHOCK__ACCOUNT__REGISTRATIONENABLED: true labels: - "traefik.enable=true" - "traefik.http.routers.openshock-api.rule=Host(`${OPENSHOCK_API_SUBDOMAIN:-api}.${OPENSHOCK_DOMAIN:-openshock.local}`)" @@ -316,6 +317,7 @@ services: 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 + OPENSHOCK__ACCOUNT__REGISTRATIONENABLED: true webui: image: ghcr.io/openshock/webui:latest From c0022a19a1df90576b97726b101a554a7e418896 Mon Sep 17 00:00:00 2001 From: Anty Date: Wed, 17 Jun 2026 20:35:38 +0200 Subject: [PATCH 3/3] feat: add admin account bootstrap steps --- docs/guides/selfhosting/index.mdx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/guides/selfhosting/index.mdx b/docs/guides/selfhosting/index.mdx index 2100f649..b2141e3a 100644 --- a/docs/guides/selfhosting/index.mdx +++ b/docs/guides/selfhosting/index.mdx @@ -440,6 +440,16 @@ server { +## 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: