| author | |
| committer | |
| log | e402d6ef71dfc310caeeb4d3579bddd9d0710594 |
| tree | 5f1900497cf85c0c5a0f8bd4626576a23e207549 |
| parent | c94f61522e07ad2783764708af19703355c3e999 |
| signature |
to avoid having a separate user like `ssh evil-git@git.evil.inc`,
instead the gambit is to have two intercept scripts to perform
routing based on the repo that is being pushed to.9 files changed, 119 insertions(+), 28 deletions(-)
compose.yaml+2-2| ... | @@ -152,7 +152,6 @@ services: | ... | @@ -152,7 +152,6 @@ services: |
| 152 | image: code.forgejo.org/forgejo/forgejo:13 | 152 | image: code.forgejo.org/forgejo/forgejo:13 |
| 153 | entrypoint: ["/bin/sh", "/custom/init/entry.sh"] | 153 | entrypoint: ["/bin/sh", "/custom/init/entry.sh"] |
| 154 | ports: | 154 | ports: |
| 155 | - 40243:22 | ||
| 156 | - 40244:3000 # port used for forgejo-runner | 155 | - 40244:3000 # port used for forgejo-runner |
| 157 | environment: | 156 | environment: |
| 158 | USER_UID: "$USER_ID" | 157 | USER_UID: "$USER_ID" |
| ... | @@ -167,6 +166,7 @@ services: | ... | @@ -167,6 +166,7 @@ services: |
| 167 | FORGEJO_OAUTH2_JWT_SECRET: "${FORGEJO_OAUTH2_JWT_SECRET:?}" | 166 | FORGEJO_OAUTH2_JWT_SECRET: "${FORGEJO_OAUTH2_JWT_SECRET:?}" |
| 168 | FORGEJO_SECURITY_SECRET_KEY: "${FORGEJO_SECURITY_SECRET_KEY:?}" | 167 | FORGEJO_SECURITY_SECRET_KEY: "${FORGEJO_SECURITY_SECRET_KEY:?}" |
| 169 | FORGEJO_SECURITY_INTERNAL_TOKEN: "${FORGEJO_SECURITY_INTERNAL_TOKEN:?}" | 168 | FORGEJO_SECURITY_INTERNAL_TOKEN: "${FORGEJO_SECURITY_INTERNAL_TOKEN:?}" |
| 169 | HOME_INFRA_HOST_DIR: "${HOME_INFRA_HOST_DIR:?}" | ||
| 170 | restart: unless-stopped | 170 | restart: unless-stopped |
| 171 | volumes: | 171 | volumes: |
| 172 | - "${APP_ROOT}/keycloak:/shared-keys:ro" | 172 | - "${APP_ROOT}/keycloak:/shared-keys:ro" |
| ... | @@ -590,7 +590,6 @@ services: | ... | @@ -590,7 +590,6 @@ services: |
| 590 | image: code.forgejo.org/forgejo/forgejo:13 | 590 | image: code.forgejo.org/forgejo/forgejo:13 |
| 591 | entrypoint: ["/bin/sh", "/custom/init/entry.sh"] | 591 | entrypoint: ["/bin/sh", "/custom/init/entry.sh"] |
| 592 | ports: | 592 | ports: |
| 593 | - 22666:22 | ||
| 594 | - 40666:3000 # port used for forgejo-runner | 593 | - 40666:3000 # port used for forgejo-runner |
| 595 | environment: | 594 | environment: |
| 596 | USER_UID: "$USER_ID" | 595 | USER_UID: "$USER_ID" |
| ... | @@ -604,6 +603,7 @@ services: | ... | @@ -604,6 +603,7 @@ services: |
| 604 | FORGEJO_SECURITY_SECRET_KEY: "${EVIL_FORGEJO_SECURITY_SECRET_KEY}" | 603 | FORGEJO_SECURITY_SECRET_KEY: "${EVIL_FORGEJO_SECURITY_SECRET_KEY}" |
| 605 | FORGEJO_SECURITY_INTERNAL_TOKEN: "${EVIL_FORGEJO_SECURITY_INTERNAL_TOKEN}" | 604 | FORGEJO_SECURITY_INTERNAL_TOKEN: "${EVIL_FORGEJO_SECURITY_INTERNAL_TOKEN}" |
| 606 | POSTGRES_PASSWORD_EVIL_FORGEJO: "${POSTGRES_PASSWORD_EVIL_FORGEJO:?}" | 605 | POSTGRES_PASSWORD_EVIL_FORGEJO: "${POSTGRES_PASSWORD_EVIL_FORGEJO:?}" |
| 606 | HOME_INFRA_HOST_DIR: "${HOME_INFRA_HOST_DIR:?}" | ||
| 607 | restart: unless-stopped | 607 | restart: unless-stopped |
| 608 | volumes: | 608 | volumes: |
| 609 | - "${APP_ROOT}/evil-infra/forgejo:/data:rw" | 609 | - "${APP_ROOT}/evil-infra/forgejo:/data:rw" |
config/evil-infra/forgejo/init/app.ini+3-3| ... | @@ -31,13 +31,13 @@ DOMAIN=git.evil.inc | ... | @@ -31,13 +31,13 @@ DOMAIN=git.evil.inc |
| 31 | SSH_DOMAIN=git.evil.inc | 31 | SSH_DOMAIN=git.evil.inc |
| 32 | HTTP_PORT=3000 | 32 | HTTP_PORT=3000 |
| 33 | ROOT_URL=https://git.evil.inc | 33 | ROOT_URL=https://git.evil.inc |
| 34 | DISABLE_SSH=false | ||
| 35 | SSH_PORT=22 | ||
| 36 | SSH_LISTEN_PORT=22 | ||
| 37 | LFS_JWT_SECRET=$FORGEJO_SERVER_LFS_JWT_SECRET | 34 | LFS_JWT_SECRET=$FORGEJO_SERVER_LFS_JWT_SECRET |
| 38 | LFS_START_SERVER=true | 35 | LFS_START_SERVER=true |
| 39 | OFFLINE_MODE=true | 36 | OFFLINE_MODE=true |
| 40 | LANDING_PAGE=/evil | 37 | LANDING_PAGE=/evil |
| 38 | START_SSH_SERVER=false | ||
| 39 | SSH_CREATE_AUTHORIZED_KEYS_FILE=false | ||
| 40 | SSH_AUTHORIZED_KEYS_COMMAND_TEMPLATE=$HOME_INFRA_HOST_DIR/config/forgejo/ssh/route.sh {{.Key.ID}} | ||
| 41 | 41 | ||
| 42 | [database] | 42 | [database] |
| 43 | DB_TYPE=postgres | 43 | DB_TYPE=postgres |
config/forgejo/init/app.ini+3-3| ... | @@ -32,13 +32,13 @@ DOMAIN=git.$HOME_DOMAIN | ... | @@ -32,13 +32,13 @@ DOMAIN=git.$HOME_DOMAIN |
| 32 | SSH_DOMAIN=git.$HOME_DOMAIN | 32 | SSH_DOMAIN=git.$HOME_DOMAIN |
| 33 | HTTP_PORT=3000 | 33 | HTTP_PORT=3000 |
| 34 | ROOT_URL=https://git.$HOME_DOMAIN/ | 34 | ROOT_URL=https://git.$HOME_DOMAIN/ |
| 35 | DISABLE_SSH=false | ||
| 36 | SSH_PORT=22 | ||
| 37 | SSH_LISTEN_PORT=22 | ||
| 38 | LFS_JWT_SECRET=$FORGEJO_SERVER_LFS_JWT_SECRET | 35 | LFS_JWT_SECRET=$FORGEJO_SERVER_LFS_JWT_SECRET |
| 39 | LFS_START_SERVER=true | 36 | LFS_START_SERVER=true |
| 40 | OFFLINE_MODE=true | 37 | OFFLINE_MODE=true |
| 41 | LANDING_PAGE=/clo | 38 | LANDING_PAGE=/clo |
| 39 | START_SSH_SERVER=false | ||
| 40 | SSH_CREATE_AUTHORIZED_KEYS_FILE=false | ||
| 41 | SSH_AUTHORIZED_KEYS_COMMAND_TEMPLATE=$HOME_INFRA_HOST_DIR/config/forgejo/ssh/route.sh {{.Key.ID}} | ||
| 42 | 42 | ||
| 43 | [database] | 43 | [database] |
| 44 | DB_TYPE=postgres | 44 | DB_TYPE=postgres |
config/forgejo/ssh/config created+3| ... | @@ -0,0 +1,3 @@ | ||
| 1 | Match User git | ||
| 2 | AuthorizedKeysCommand /bin/python /mnt/storage1/apps/home-infra/config/forgejo/ssh/keys.py %u %t %k | ||
| 3 | AuthorizedKeysCommandUser git | ||
config/forgejo/ssh/keys.py created+57| ... | @@ -0,0 +1,57 @@ | ||
| 1 | #!/usr/bin/env python3 | ||
| 2 | import sys | ||
| 3 | import subprocess | ||
| 4 | import re | ||
| 5 | |||
| 6 | user, key_type, key = sys.argv[1:4] | ||
| 7 | |||
| 8 | |||
| 9 | def get_key_id(container: str): | ||
| 10 | try: | ||
| 11 | result = subprocess.run( | ||
| 12 | [ | ||
| 13 | "sudo", | ||
| 14 | "/usr/bin/docker", | ||
| 15 | "exec", | ||
| 16 | "-u", | ||
| 17 | "3000:3000", | ||
| 18 | container, | ||
| 19 | "/usr/local/bin/forgejo", | ||
| 20 | "keys", | ||
| 21 | "-c", | ||
| 22 | "/custom/conf/app.ini", | ||
| 23 | "-e", | ||
| 24 | "git", | ||
| 25 | "-u", | ||
| 26 | user, | ||
| 27 | "-t", | ||
| 28 | key_type, | ||
| 29 | "-k", | ||
| 30 | key, | ||
| 31 | ], | ||
| 32 | capture_output=True, | ||
| 33 | text=True, | ||
| 34 | check=False, | ||
| 35 | ) | ||
| 36 | match = re.search(r"route\.sh (\d+)", result.stdout) | ||
| 37 | return match.group(1) if match else None | ||
| 38 | except: | ||
| 39 | return None | ||
| 40 | |||
| 41 | |||
| 42 | clover_id = get_key_id("forgejo") | ||
| 43 | evil_id = get_key_id("evil-forgejo") | ||
| 44 | |||
| 45 | if not clover_id and not evil_id: | ||
| 46 | sys.exit(0) | ||
| 47 | |||
| 48 | args: list[str] = [] | ||
| 49 | if clover_id: | ||
| 50 | args.extend(["--clover", clover_id]) | ||
| 51 | if evil_id: | ||
| 52 | args.extend(["--evil", evil_id]) | ||
| 53 | |||
| 54 | cmd = "/mnt/storage1/apps/home-infra/config/forgejo/ssh/route.sh " + " ".join(args) | ||
| 55 | print( | ||
| 56 | f'command="{cmd}",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty,no-user-rc,restrict {key_type} {key}' | ||
| 57 | ) | ||
config/forgejo/ssh/route.sh created+48| ... | @@ -0,0 +1,48 @@ | ||
| 1 | #!/bin/sh | ||
| 2 | clover_id="" | ||
| 3 | evil_id="" | ||
| 4 | |||
| 5 | while [ $# -gt 0 ]; do | ||
| 6 | case "$1" in | ||
| 7 | --clover) | ||
| 8 | clover_id="$2" | ||
| 9 | shift 2 | ||
| 10 | ;; | ||
| 11 | --evil) | ||
| 12 | evil_id="$2" | ||
| 13 | shift 2 | ||
| 14 | ;; | ||
| 15 | *) shift ;; | ||
| 16 | esac | ||
| 17 | done | ||
| 18 | |||
| 19 | repo="${SSH_ORIGINAL_COMMAND#* }" | ||
| 20 | repo="${repo%\'*}" | ||
| 21 | repo="${repo#\'}" | ||
| 22 | repo="${repo#/}" | ||
| 23 | |||
| 24 | case "$repo" in | ||
| 25 | *[!a-zA-Z0-9/_.-]*) | ||
| 26 | echo "invalid repo name: $repo" >&2 | ||
| 27 | exit 1 | ||
| 28 | ;; | ||
| 29 | *..*) | ||
| 30 | echo "invalid repo name: $repo" >&2 | ||
| 31 | exit 1 | ||
| 32 | ;; | ||
| 33 | /*) | ||
| 34 | echo "invalid repo name: $repo" >&2 | ||
| 35 | exit 1 | ||
| 36 | ;; | ||
| 37 | esac | ||
| 38 | |||
| 39 | if [ -d "/mnt/storage1/apps/forgejo/git/repositories/${repo}" ]; then | ||
| 40 | [ -z "$clover_id" ] && echo "ssh key is not configured for repository on git.paperclover.net" >&2 && exit 1 | ||
| 41 | exec sudo docker exec -i -u git forgejo /usr/bin/env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" /usr/local/bin/forgejo --config=/custom/conf/app.ini serv key-"$clover_id" | ||
| 42 | elif [ -d "/mnt/storage1/apps/evil-infra/forgejo/git/repositories/${repo}" ]; then | ||
| 43 | [ -z "$evil_id" ] && echo "ssh key is not configured for repository on git.evil.inc" >&2 && exit 1 | ||
| 44 | exec sudo docker exec -i -u git evil-forgejo /usr/bin/env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" /usr/local/bin/forgejo --config=/custom/conf/app.ini serv key-"$evil_id" | ||
| 45 | else | ||
| 46 | echo "repo not found" >&2 | ||
| 47 | exit 1 | ||
| 48 | fi | ||
docker.sh created+2| ... | @@ -0,0 +1,2 @@ | ||
| 1 | #!/bin/sh | ||
| 2 | ssh clo@192.168.0.1 -- cd /mnt/storage1/apps/home-infra \&\& sudo docker "$@" | ||
generate-env.sh+1| ... | @@ -10,6 +10,7 @@ fi | ... | @@ -10,6 +10,7 @@ fi |
| 10 | printf "generating...\n" | 10 | printf "generating...\n" |
| 11 | 11 | ||
| 12 | template() { | 12 | template() { |
| 13 | add "HOME_INFRA_HOST_DIR" "$PWD" | ||
| 13 | add "HOME_DOMAIN" "local.test" | 14 | add "HOME_DOMAIN" "local.test" |
| 14 | add "ADMIN_EMAIL" "" | 15 | add "ADMIN_EMAIL" "" |
| 15 | add "USER_ID" "$(id -u)" | 16 | add "USER_ID" "$(id -u)" |
readme.md-20| ... | @@ -3,26 +3,6 @@ | ... | @@ -3,26 +3,6 @@ |
| 3 | this codebase is used for all docker services on my home nas, including personal | 3 | this codebase is used for all docker services on my home nas, including personal |
| 4 | customization. | 4 | customization. |
| 5 | 5 | ||
| 6 | ## usage | ||
| 7 | |||
| 8 | ``` | ||
| 9 | git clone https://git.paperclover.net/clo/home-infra.git | ||
| 10 | cd home-infra | ||
| 11 | |||
| 12 | # setup repo | ||
| 13 | rm config/font/* | ||
| 14 | git clone https://git.paperclover.net/clo/sitegen.git | ||
| 15 | cp .env.example .env | ||
| 16 | |||
| 17 | # fill secrets | ||
| 18 | vi .env | ||
| 19 | vi secrets/openvpn-credentials.txt | ||
| 20 | |||
| 21 | docker compose up -d | ||
| 22 | ``` | ||
| 23 | |||
| 24 | ## license | ||
| 25 | |||
| 26 | this repository is for example usage only. you may not re-host it in full, | 6 | this repository is for example usage only. you may not re-host it in full, |
| 27 | privately or publicly, but you may learn from my usage. please note that some | 7 | privately or publicly, but you may learn from my usage. please note that some |
| 28 | components here are under licenses which do not permit redistribution. | 8 | components here are under licenses which do not permit redistribution. |