From 788fb420ace464f4f92b745c3a7f58408e00bb6a Mon Sep 17 00:00:00 2001 From: Mayel de Borniol Date: Sat, 18 Oct 2025 14:49:12 +0100 Subject: [PATCH 1/2] add FALLBACK_REDIRECT_URL to be able to redirect any unknown paths to a different domain --- .env.sample | 9 ++++++++- abra.sh | 4 ++-- compose.yml | 3 +++ default.conf.tmpl | 24 +++++++++++++++++++----- entrypoint.git-pull.sh | 2 +- 5 files changed, 33 insertions(+), 9 deletions(-) diff --git a/.env.sample b/.env.sample index 98d1b56..70d33d8 100644 --- a/.env.sample +++ b/.env.sample @@ -6,6 +6,7 @@ DOMAIN=custom-html.example.com LETS_ENCRYPT_ENV=production COMPOSE_FILE="compose.yml" +HTML_ROOT=/usr/share/nginx/html # Single Sign On via Traefik "file provider" #COMPOSE_FILE="$COMPOSE_FILE:compose.sso.yml" @@ -13,7 +14,9 @@ COMPOSE_FILE="compose.yml" # Git-pull regularly #COMPOSE_FILE="$COMPOSE_FILE:compose.git-pull.yml" #GIT_REPO_URL="https://git.coopcloud.tech/dalmationer/hexbomb.gay" -#CRON_SCHEDULE="*/1 * * * *" +#GIT_BRANCH=main +#CRON_SCHEDULE="*/10 * * * *" # Default: every 10 minutes +# HTML_ROOT=/git # Optionally redirect the entire domain or a sub-path: # path under which you want to redirect all URLs (with trailing slash): @@ -27,6 +30,10 @@ COMPOSE_FILE="compose.yml" # Optionally handle all URL requests using a single file (commonly index.html) #SINGLE_PAGE_SITE_HANDLER=/index.html +# Optionally redirect URL requests if not file is found for the requested path +# FALLBACK_REDIRECT_URL=https://coopcloud.tech/ +# FALLBACK_REDIRECT_TYPE=302 + # Enable an SSH server to allow SFTP uploads to the web root #COMPOSE_FILE="$COMPOSE_FILE:compose.sftp.yml" #PUBLIC_KEY="ssh-ed25519 AAAAC3NzaJ1lZDI1NTE5AAAAIXqf4nxUxuGmLOaxXXXXXXXXoM/GwhcrAgmtbgXToaYmCJ user@host" # Replace with a public key you generate \ No newline at end of file diff --git a/abra.sh b/abra.sh index 3ad0c18..e75b349 100644 --- a/abra.sh +++ b/abra.sh @@ -1,2 +1,2 @@ -export NGINX_DEFAULT_CONF_VERSION=v6 -export ENTRYPOINT_CONF_VERSION=v3 +export NGINX_DEFAULT_CONF_VERSION=v10 +export ENTRYPOINT_CONF_VERSION=v4 diff --git a/compose.yml b/compose.yml index d22dbb4..829633b 100644 --- a/compose.yml +++ b/compose.yml @@ -24,9 +24,12 @@ services: - "backupbot.backup.path=/usr/share/nginx/html" environment: - DEFAULT_CONF_FILE=/etc/nginx/conf.d/default.conf + - HTML_ROOT - REDIRECT_FROM_PATH - REDIRECT_TO_URL - REDIRECT_TYPE + - FALLBACK_REDIRECT_URL + - FALLBACK_REDIRECT_TYPE volumes: - content:/usr/share/nginx/html configs: diff --git a/default.conf.tmpl b/default.conf.tmpl index 2262be6..6161752 100644 --- a/default.conf.tmpl +++ b/default.conf.tmpl @@ -8,20 +8,34 @@ server { #access_log /var/log/nginx/host.access.log main; location / { - root /usr/share/nginx/html; + root {{ env "HTML_ROOT" }}; index index.html index.htm; - + {{ if env "REDIRECT_TO_URL" }} rewrite ^{{ env "REDIRECT_FROM_PATH" }}(.*)$ {{ env "REDIRECT_TO_URL" }}$1 {{ env "REDIRECT_TYPE" }}; {{ end }} - {{ if env "SINGLE_PAGE_SITE_HANDLER" }} - try_files $uri $uri/ {{ env "SINGLE_PAGE_SITE_HANDLER" }} =404; + {{ if env "FALLBACK_REDIRECT_URL" }} + # redirect unknown URLs (no matching files) to other address + try_files $uri $uri/ @fallback_redirect; {{ else }} - try_files $uri $uri/ $uri.html =404; + {{ if env "SINGLE_PAGE_SITE_HANDLER" }} + # serve SPA handler + try_files $uri $uri/ {{ env "SINGLE_PAGE_SITE_HANDLER" }} =404; + {{ else }} + # serve static files or regular 404 as usual + try_files $uri $uri/ $uri.html =404; + {{ end }} {{ end }} } + {{ if env "FALLBACK_REDIRECT_URL" }} + location @fallback_redirect { + return {{ env "FALLBACK_REDIRECT_TYPE" }} {{ env "FALLBACK_REDIRECT_URL" }}$request_uri; + } + {{ end }} + + # Standard static 404 error page error_page 404 /404.html; location = /404.html { root /usr/share/nginx/html; diff --git a/entrypoint.git-pull.sh b/entrypoint.git-pull.sh index 16682ef..5278491 100644 --- a/entrypoint.git-pull.sh +++ b/entrypoint.git-pull.sh @@ -4,7 +4,7 @@ if [ ! -d /git/.git ]; then echo "No repo found, emptying /git/ directory" rm -r /git/* echo "Cloning $GIT_REPO_URL into /git" - git clone "$GIT_REPO_URL" /git + git clone -b "$GIT_BRANCH" --single-branch "$GIT_REPO_URL" /git else echo "Updating /git" git pull -- 2.49.0 From 514040fcebc68f5f6639478a97c53d174034516a Mon Sep 17 00:00:00 2001 From: Mayel de Borniol Date: Sat, 18 Oct 2025 21:32:13 +0100 Subject: [PATCH 2/2] remove HTML_ROOT & update readme --- .env.sample | 2 -- README.md | 64 +++++++++++++++++++++++++++++++++++++++++++++++ abra.sh | 2 +- compose.yml | 1 - default.conf.tmpl | 2 +- 5 files changed, 66 insertions(+), 5 deletions(-) diff --git a/.env.sample b/.env.sample index 70d33d8..26e9282 100644 --- a/.env.sample +++ b/.env.sample @@ -6,7 +6,6 @@ DOMAIN=custom-html.example.com LETS_ENCRYPT_ENV=production COMPOSE_FILE="compose.yml" -HTML_ROOT=/usr/share/nginx/html # Single Sign On via Traefik "file provider" #COMPOSE_FILE="$COMPOSE_FILE:compose.sso.yml" @@ -16,7 +15,6 @@ HTML_ROOT=/usr/share/nginx/html #GIT_REPO_URL="https://git.coopcloud.tech/dalmationer/hexbomb.gay" #GIT_BRANCH=main #CRON_SCHEDULE="*/10 * * * *" # Default: every 10 minutes -# HTML_ROOT=/git # Optionally redirect the entire domain or a sub-path: # path under which you want to redirect all URLs (with trailing slash): diff --git a/README.md b/README.md index c375358..2b0b52a 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,23 @@ Custom HTML website, served using Nginx. abra app cp YOURAPPDOMAIN index.html app:/usr/share/nginx/html ``` +## Downloading and auto-updating from a Git repository + +To automatically pull website contents from a Git repository on a schedule: + +1. `abra app config YOURAPPDOMAIN` +2. Add or uncomment these lines and configure your repository and update schedule: +``` +COMPOSE_FILE="$COMPOSE_FILE:compose.git-pull.yml" +GIT_REPO_URL="https://git.coopcloud.tech/yourorg/yourrepo" +GIT_BRANCH=main +CRON_SCHEDULE="*/10 * * * *" # Default: every 10 minutes +``` +3. `abra app deploy YOURAPPDOMAIN` +4. As the git-pull service has `replicas: 0` in `compose.git-pull.yml` and doesn't run by itself. It requires either: +- Deploying an instance of the [`coop-cloud/swarm-cronjob`] recipe on your server, OR +- A manual cronjob on the server running: `docker service scale _git=1` + ## Allowing upload via SSH/SFTP To allow management of your site's files using scp, rsync or other SSH-based tools: 1. If you don't already have one, generate an SSH keypair using `ssh-keygen` @@ -42,6 +59,53 @@ To allow management of your site's files using scp, rsync or other SSH-based too 4. Test the SSH connection: `ssh -p 2220 sftp@YOURAPPDOMAIN` 5. You can copy local files into the server's web root with a command like: `scp -r -P 2220 * sftp@YOURAPPDOMAIN:/content` +## Redirect options + +### Full redirect (of all URLs under specific path) + +To redirect the entire domain or a specific path to another URL: + +1. `abra app config YOURAPPDOMAIN` +2. Add or uncomment these lines: +``` +REDIRECT_FROM_PATH=/ # Path to redirect from (with trailing slash) +REDIRECT_TO_URL=https://example.com/website/ # Target URL (with trailing slash) +REDIRECT_TYPE=redirect # Use "redirect" (for HTTP 302) or "permanent" (for 301) +``` +3. `abra app deploy YOURAPPDOMAIN` + +This will redirect all requests matching `REDIRECT_FROM_PATH` to `REDIRECT_TO_URL`, carrying over the path. For example, `/blog/post` would redirect to `https://example.com/website/blog/post`. + +### Fallback redirect for paths not matching a file + +To serve static files normally but redirect requests for all non-existent paths to a dynamic site: + +1. `abra app config YOURAPPDOMAIN` +2. Add or uncomment these lines: +``` +FALLBACK_REDIRECT_URL=https://dynamic-site.example.com +FALLBACK_REDIRECT_TYPE=302 +``` +3. `abra app deploy YOURAPPDOMAIN` + +This is useful for serving a static site alongside a dynamic one (that is running on a different [sub]domain) on the same domain. Existing static files are served directly, while missing URLs are redirected to the dynamic site with the full path preserved. + +### Single-page application (SPA) handler + +Similarly, to serve all non-existent paths with a single HTML file (common for React, Vue, etc.): + +1. `abra app config YOURAPPDOMAIN` +2. Add or uncomment this line: +``` +SINGLE_PAGE_SITE_HANDLER=/index.html +``` +3. `abra app deploy YOURAPPDOMAIN` + +This will serve the contents `/index.html` (as a rewrite rather than a redirect) for any route that doesn't match an existing file, allowing client-side routing to work properly. + +**Note:** `FALLBACK_REDIRECT_URL` and `SINGLE_PAGE_SITE_HANDLER` are mutually exclusive options. + [`abra`]: https://git.autonomic.zone/autonomic-cooperative/abra [`coop-cloud/traefik`]: https://git.autonomic.zone/coop-cloud/traefik +[`coop-cloud/swarm-cronjob`]: https://git.coopcloud.tech/coop-cloud/swarm-cronjob diff --git a/abra.sh b/abra.sh index e75b349..30ad931 100644 --- a/abra.sh +++ b/abra.sh @@ -1,2 +1,2 @@ -export NGINX_DEFAULT_CONF_VERSION=v10 +export NGINX_DEFAULT_CONF_VERSION=v11 export ENTRYPOINT_CONF_VERSION=v4 diff --git a/compose.yml b/compose.yml index 829633b..2e15ad3 100644 --- a/compose.yml +++ b/compose.yml @@ -24,7 +24,6 @@ services: - "backupbot.backup.path=/usr/share/nginx/html" environment: - DEFAULT_CONF_FILE=/etc/nginx/conf.d/default.conf - - HTML_ROOT - REDIRECT_FROM_PATH - REDIRECT_TO_URL - REDIRECT_TYPE diff --git a/default.conf.tmpl b/default.conf.tmpl index 6161752..6e33601 100644 --- a/default.conf.tmpl +++ b/default.conf.tmpl @@ -8,7 +8,7 @@ server { #access_log /var/log/nginx/host.access.log main; location / { - root {{ env "HTML_ROOT" }}; + root /usr/share/nginx/html; index index.html index.htm; {{ if env "REDIRECT_TO_URL" }} -- 2.49.0