diff --git a/.gitignore b/.gitignore index dac5c63..e2ce507 100644 --- a/.gitignore +++ b/.gitignore @@ -6,5 +6,5 @@ clusters.json /nginx /autossl .env -ncc /venv +ncc.tar diff --git a/README.md b/README.md index 877fd07..7d1caf6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,16 @@ -# Nginx configurator (patent for that name is pending...) +# Nginx cluster configurator - ncc + +Manages the local nginx configuration and replicates changes to a backup. + +## Features + +* Allows the editing of services and using a template for new ones. Makes sure + the configuration is valid before reloading the cluster (nginx). +* Automatically obtains SSL certificates and replicates them to the cluster (dehydrated). +* Will only make changes on the master server (keepalived). # TODO + * Prepare config templates for nginx and dehydrated? * document dhparam.pem generation (`openssl dhparam -out ssl-dhparams.pem 4096` in /etc/autossl) * Limit current SSH keys to only config rsync and nginx reload @@ -8,16 +18,41 @@ * Create a guide how to use it to intrawiki * Teach everybody how to use it... -# Setup -* `python3 -m venv .venv` -* `source .venv/bin/activate` -* `pip3 install -r ./requirements.txt` -* `cp env.sample .env` # and customize to your needs +# Build +Run `build.sh` on a linux(-ish) machine. The output is a tarball `ncc.tar`. +# Installation +* Extract `ncc.tar` to a location on the server +* Copy configuration `config` to `/etc/ncc` and modify to suit your environment +* Add `/etc/ncc/ncc-hook.sh` as a hook to your `dehydrated` installation +* Add `ncc` to your `PATH` + +# Usage + +``` +Usage: ncc [OPTIONS] COMMAND [ARGS]... + + Update the nginx cluster configuration + + MUST BE RAN ON MASTER (will detect automatically) + +Options: + --skip-master-check + --help Show this message and exit. + +Commands: + autossl Renew SSL certificates and replicate changes + delete Delete a service + edit Edit a service + list List exsiting services and domain names associated with them + new Create a new service + reload Replicate the local config and reload the nginx cluster +``` # Contributions + Please use `black` formatter. -You can automate the process by running `cp .githooks/pre-commit .git/hooks/pre-commit && chmod +x .git/hooks/pre-commit` after pulling the repository. \ No newline at end of file +You can automate the process by running `cp .githooks/pre-commit .git/hooks/pre-commit && chmod +x .git/hooks/pre-commit` after pulling the repository. diff --git a/build.sh b/build.sh index a66b177..eb09a56 100755 --- a/build.sh +++ b/build.sh @@ -1,7 +1,9 @@ +#!/bin/bash DIR=$(mktemp -d) pip install -r requirements.txt --target="$DIR" cp -r nginx_configurator "$DIR" +cp -r config "$DIR" #python3 -m zipapp -p "/bin/python3" -m "nginx_configurator.main:cli" -o ncc "$DIR" diff --git a/clusters.json.example b/clusters.json.example deleted file mode 100644 index 9bb55ad..0000000 --- a/clusters.json.example +++ /dev/null @@ -1,19 +0,0 @@ -{ - "clusters":[ - { - "name":"dummy1", - "nodes": [ - "10.0.0.1", - "10.0.0.2", - "10.0.0.3" - ] - }, - { - "name":"dummy2", - "nodes": [ - "127.0.0.1", - "127.0.0.2" - ] - } - ] - } \ No newline at end of file diff --git a/env.sample b/config/env similarity index 50% rename from env.sample rename to config/env index 9927f73..6a9fdf4 100644 --- a/env.sample +++ b/config/env @@ -1,5 +1,5 @@ NGINX_DIR="/etc/nginx" DOMAINS_TXT="/etc/autossl/domains.txt" -DEHYDRATED_LOC="/etc/autossl/dehydrated.sh" +DEHYDRATED_BIN="/etc/autossl/dehydrated.sh" REMOTE="10.0.0.1" -REMOTE_SSH_KEY="./ssh.key" \ No newline at end of file +REMOTE_SSH_KEY="/etc/ncc/ssh.key" diff --git a/config/ncc-hook.sh b/config/ncc-hook.sh new file mode 100755 index 0000000..466096b --- /dev/null +++ b/config/ncc-hook.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# This hook is part of ncc. It creates a marker file on new cert deployments, +# so that ncc knows when to reload the cluster. + +deploy_cert() { + touch /etc/autossl/trigger; +} + +deploy_ocsp() { + touch /tmp/ncc-ssl-trigger; +} + +startup_hook() { + [ -f /tmp/ncc-ssl-trigger ] && rm /tmp/ncc-ssl-trigger || true; +} + +fn_exists() { declare -F "$1" > /dev/null; } + +HANDLER="$1"; shift +if fn_exists "$HANDLER"; then + "$HANDLER" "$@"; +fi diff --git a/nginx_configurator/main.py b/nginx_configurator/main.py index 5e06b48..10cd5ea 100644 --- a/nginx_configurator/main.py +++ b/nginx_configurator/main.py @@ -9,15 +9,15 @@ from . import sysaction, certs from .sysaction import quit_on_err from .templating import jinja -load_dotenv(os.getenv("DOTENV_PATH", "/etc/ncc/.env")) +load_dotenv(os.getenv("DOTENV_PATH", "/etc/ncc/env")) NGINX_DIR = Path(os.getenv("NGINX_DIR", "/etc/nginx")) DOMAINS_TXT = Path(os.getenv("DOMAINS_TXT", "/etc/dehydrated/domains.txt")) REMOTE = os.getenv("REMOTE") REMOTE_SSH_KEY = os.getenv("REMOTE_SSH_KEY") -DEHYDRATED_LOC = os.getenv("DEHYDRATED_LOC", "/etc/dehydrated/dehydrated.sh") +DEHYDRATED_BIN = os.getenv("DEHYDRATED_BIN", "dehydrated") DEHYDRATED_TRIGGER_FILE = Path( - os.getenv("DEHYDRATED_TRIGGER_FILE", "/etc/dehydrated/trigger") + os.getenv("DEHYDRATED_TRIGGER_FILE", "/tmp/ncc-ssl-trigger") ) CLUSTERS_FILE = Path(os.getenv("CLUSTERS_FILE", "/etc/ncc/clusters.json")) @@ -65,7 +65,7 @@ def reload(): # obtain certs quit_on_err( - sysaction.run_dehydrated(DEHYDRATED_LOC), + sysaction.run_dehydrated(DEHYDRATED_BIN), additional_info="Failed to run dehydrated", ) certs.generate_ssl_configs(NGINX_DIR / "ssl", [d[1] for d in directives]) @@ -344,7 +344,7 @@ def autossl(): # obtain certs quit_on_err( - sysaction.run_dehydrated(DEHYDRATED_LOC), + sysaction.run_dehydrated(DEHYDRATED_BIN), additional_info="Failed to run dehydrated", )