Compare commits
19 Commits
ecda3d4369
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2bbf9b3f53 | ||
|
|
86339f5115 | ||
|
|
5b55b02a76 | ||
|
|
d7cb02f506 | ||
|
|
3ca2a092fd | ||
|
|
5e52facc5c | ||
|
|
7914368111 | ||
|
|
586c4b47bc | ||
|
|
cb530aa864 | ||
|
|
a5d0b1cb2f | ||
|
|
b7537179c9 | ||
|
|
be29375bee | ||
|
|
454a6fe00c | ||
|
|
405e1fc05c | ||
|
|
34898d9b11 | ||
|
|
be34df6324 | ||
|
|
f92924b74f | ||
|
|
cd190d2e3f | ||
|
|
13438044e6 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
certs/
|
certs/
|
||||||
|
*.log
|
||||||
@@ -7,7 +7,9 @@
|
|||||||
protocols tls1.3
|
protocols tls1.3
|
||||||
client_auth {
|
client_auth {
|
||||||
mode require_and_verify
|
mode require_and_verify
|
||||||
trusted_ca_cert_file /certs/root_ca.crt
|
trust_pool file {
|
||||||
|
pem_file /certs/root_ca.crt
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reverse_proxy rest-server:8000
|
reverse_proxy rest-server:8000
|
||||||
|
|||||||
78
README.md
78
README.md
@@ -16,7 +16,8 @@ Connect solely through wireguard to `192.168.1.142` and serve the REST server wi
|
|||||||
|
|
||||||
## Restic Repos
|
## Restic Repos
|
||||||
|
|
||||||
`/etc/fstab` entry:
|
`/etc/fstab` entry on Proxmox host:
|
||||||
|
|
||||||
```
|
```
|
||||||
john-nas:/volume1/restic /mnt/nfs/restic nfs nofail,_netdev,x-systemd.automount,x-systemd.idle-timeout=600,timeo=14,retrans=3,hard,tcp,nfsvers=3 0 0
|
john-nas:/volume1/restic /mnt/nfs/restic nfs nofail,_netdev,x-systemd.automount,x-systemd.idle-timeout=600,timeo=14,retrans=3,hard,tcp,nfsvers=3 0 0
|
||||||
```
|
```
|
||||||
@@ -36,27 +37,41 @@ pct set 103 -mp0 /mnt/nfs/restic,mp=/mnt/restic
|
|||||||
Generate a new private key and (public) certificate in the right places. This will use the `admin` provisioner.
|
Generate a new private key and (public) certificate in the right places. This will use the `admin` provisioner.
|
||||||
|
|
||||||
```
|
```
|
||||||
step ca certificate soteria.john-stream.com certs/soteria.crt certs/soteria.key --provisioner admin
|
export HOSTNAME=$(hostname -s) && \
|
||||||
|
export DOMAIN="john-stream.com" && \
|
||||||
|
export CERT_DIR="/var/lib/tls" && \
|
||||||
|
export IP_ADDRESS=$(ip -4 addr show dev eth0 | awk '/inet /{print $2}' | cut -d/ -f1)
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
(umask 077; mkdir -p "$CERT_DIR") && cd "$CERT_DIR" && \
|
||||||
|
step ca root root_ca.crt && \
|
||||||
|
step ca certificate "$HOSTNAME" cert.pem key.pem \
|
||||||
|
--san "$HOSTNAME" \
|
||||||
|
--san "$HOSTNAME.$DOMAIN" \
|
||||||
|
--san "$IP_ADDRESS" \
|
||||||
|
--san spiffe://john-stream.com/role/docker-agent \
|
||||||
|
--provisioner admin
|
||||||
|
```
|
||||||
|
|
||||||
|
Convert the key for Envoy to use:
|
||||||
|
|
||||||
|
```
|
||||||
|
(umask 027; openssl pkcs8 -topk8 -nocrypt -in key.pem -out key_pkcs8.pem)
|
||||||
```
|
```
|
||||||
|
|
||||||
Check the resultant certificate:
|
Check the resultant certificate:
|
||||||
|
|
||||||
```
|
```
|
||||||
openssl x509 -noout -subject -issuer -ext extendedKeyUsage -ext subjectAltName -in certs/soteria.crt
|
openssl x509 -noout -subject -issuer -ext extendedKeyUsage,subjectAltName -in /var/lib/tls/cert.pem
|
||||||
```
|
```
|
||||||
|
|
||||||
Set up renewal
|
## Envoy Proxy
|
||||||
|
|
||||||
```bash
|
Validate config:
|
||||||
sudo ./scripts/install_services.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Test renewal
|
|
||||||
|
|
||||||
```
|
|
||||||
systemctl start cert-renewer.service && \
|
|
||||||
systemctl status cert-renewer.service --no-pager && \
|
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker compose run -it --rm envoy --mode validate -c /etc/envoy/envoy.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
## Clients
|
## Clients
|
||||||
@@ -71,30 +86,37 @@ curl -sL https://gitea.john-stream.com/john/soteria/raw/branch/main/scripts/setu
|
|||||||
curl -sL https://gitea.john-stream.com/john/soteria/raw/branch/main/scripts/check_status.sh | bash
|
curl -sL https://gitea.john-stream.com/john/soteria/raw/branch/main/scripts/check_status.sh | bash
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -sL https://gitea.john-stream.com/john/soteria/raw/branch/main/scripts/wizard_setup.sh | bash
|
||||||
|
```
|
||||||
|
|
||||||
### Manual Setup
|
### Manual Setup
|
||||||
|
|
||||||
Set up provisioner password by running this and pasting in the current JWK provisioner password for `admin`
|
Set up provisioner password by running this and pasting in the current JWK provisioner password for `admin`
|
||||||
|
|
||||||
```
|
```
|
||||||
read -s secret && (umask 077; echo "$secret" > $(step path)/certs/secret.txt)
|
export HOSTNAME=$(hostname -s) && \
|
||||||
```
|
export DOMAIN="john-stream.com" && \
|
||||||
|
export CERT_DIR="/var/lib/tls" && \
|
||||||
Generate the client TLS private key and (public) certificate for mTLS. This will combine them both into a file called `restic.pem`, which can be used with the `--tls-client-cert` option with the restic CLI.
|
export IP_ADDRESS=$(ip -4 addr show dev eth0 | awk '/inet /{print $2}' | cut -d/ -f1) && \
|
||||||
|
(umask 077; mkdir -p "$CERT_DIR" && cd "$CERT_DIR" && \
|
||||||
```
|
step ca root root_ca.crt && \
|
||||||
cd $(step path)/certs && \
|
step ca certificate "$HOSTNAME" cert.pem key.pem \
|
||||||
step ca certificate \
|
--san "$HOSTNAME" \
|
||||||
--provisioner admin --password-file secret.txt \
|
--san "$HOSTNAME.$DOMAIN" \
|
||||||
$(hostnamectl hostname) restic.crt restic.key && \
|
--san "$IP_ADDRESS" \
|
||||||
(umask 077; cat restic.crt restic.key > restic.pem)
|
--san spiffe://john-stream.com/role/docker-agent \
|
||||||
|
--provisioner admin && \
|
||||||
|
cat {cert,key}.pem > restic.pem) && \
|
||||||
|
chmod 644 cert.pem root_ca.crt
|
||||||
```
|
```
|
||||||
|
|
||||||
Need restic 0.16+ for the env vars `RESTIC_CACERT` and `RESTIC_TLS_CLIENT_CERT` to work.
|
Need restic 0.16+ for the env vars `RESTIC_CACERT` and `RESTIC_TLS_CLIENT_CERT` to work.
|
||||||
|
|
||||||
```
|
```
|
||||||
export RESTIC_CACERT=$(step path)/certs/root_ca.crt
|
export RESTIC_CACERT=$(step path)/certs/root_ca.crt && \
|
||||||
export RESTIC_TLS_CLIENT_CERT=$(step path)/certs/restic.pem
|
export RESTIC_TLS_CLIENT_CERT=$(step path)/certs/restic.pem && \
|
||||||
export RESTIC_REPOSITORY=rest:https://soteria.john-stream.com/john-ubuntu
|
export RESTIC_REPOSITORY=rest:https://soteria.john-stream.com/john-ubuntu && \
|
||||||
export RESTIC_PASSWORD_FILE=$(readlink -f ~/.config/resticprofile/password.txt)
|
export RESTIC_PASSWORD_FILE=$(readlink -f ~/.config/resticprofile/password.txt)
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -106,6 +128,8 @@ restic snapshots
|
|||||||
|
|
||||||
### Installing Latest Binary
|
### Installing Latest Binary
|
||||||
|
|
||||||
|
Do this in case the restic version from apt is too old.
|
||||||
|
|
||||||
```
|
```
|
||||||
curl -s https://api.github.com/repos/restic/restic/releases/latest | grep tag_name
|
curl -s https://api.github.com/repos/restic/restic/releases/latest | grep tag_name
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -8,16 +8,16 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
OPTIONS: --no-auth
|
OPTIONS: --no-auth
|
||||||
|
|
||||||
caddy:
|
envoy:
|
||||||
image: caddy:alpine
|
image: envoyproxy/envoy:v1.33-latest
|
||||||
container_name: caddy
|
user: root
|
||||||
|
container_name: envoy
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- "443:443"
|
- "443:10000"
|
||||||
volumes:
|
volumes:
|
||||||
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
- ./envoy.yaml:/etc/envoy/envoy.yaml:ro
|
||||||
- ./certs/soteria.crt:/certs/soteria.crt:ro
|
- /var/lib/tls:/certs
|
||||||
- ./certs/soteria.key:/certs/soteria.key:ro
|
- ./access.log:/var/log/envoy/access.log
|
||||||
- ${HOME}/.step/certs/root_ca.crt:/certs/root_ca.crt:ro
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- rest-server
|
- rest-server
|
||||||
|
|||||||
122
envoy.yaml
Normal file
122
envoy.yaml
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
static_resources:
|
||||||
|
# --8<-- [start:listener]
|
||||||
|
listeners:
|
||||||
|
- name: listener_0
|
||||||
|
address:
|
||||||
|
socket_address:
|
||||||
|
address: 0.0.0.0
|
||||||
|
port_value: 10000
|
||||||
|
# --8<-- [end:listener]
|
||||||
|
filter_chains:
|
||||||
|
- filter_chain_match:
|
||||||
|
server_names: ["*.john-stream.com"]
|
||||||
|
# --8<-- [start:transport_socket]
|
||||||
|
- transport_socket:
|
||||||
|
name: envoy.transport_sockets.tls
|
||||||
|
typed_config:
|
||||||
|
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
|
||||||
|
require_client_certificate: true
|
||||||
|
common_tls_context:
|
||||||
|
tls_params:
|
||||||
|
tls_minimum_protocol_version: TLSv1_3 # (1)!
|
||||||
|
validation_context:
|
||||||
|
trusted_ca: { filename: /certs/root_ca.crt }
|
||||||
|
match_typed_subject_alt_names:
|
||||||
|
- san_type: URI
|
||||||
|
matcher:
|
||||||
|
prefix: spiffe://john-stream.com # (2)!
|
||||||
|
tls_certificates:
|
||||||
|
- certificate_chain: { filename: /certs/cert.pem }
|
||||||
|
private_key: { filename: /certs/key_pkcs8.pem } # (3)!
|
||||||
|
# --8<-- [end:transport_socket]
|
||||||
|
filters:
|
||||||
|
- name: envoy.filters.network.http_connection_manager
|
||||||
|
typed_config:
|
||||||
|
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
|
||||||
|
stat_prefix: ingress_http
|
||||||
|
use_remote_address: true
|
||||||
|
http2_protocol_options:
|
||||||
|
max_concurrent_streams: 100
|
||||||
|
# --8<-- [start:access_log]
|
||||||
|
access_log:
|
||||||
|
- name: envoy.access_loggers.file
|
||||||
|
typed_config:
|
||||||
|
"@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
|
||||||
|
path: "/var/log/envoy/access.log"
|
||||||
|
# --8<-- [end:access_log]
|
||||||
|
# --8<-- [start:cluster_route]
|
||||||
|
route_config:
|
||||||
|
name: local_route
|
||||||
|
virtual_hosts:
|
||||||
|
- name: local_service
|
||||||
|
domains: ["*"]
|
||||||
|
routes:
|
||||||
|
- match:
|
||||||
|
prefix: "/"
|
||||||
|
route:
|
||||||
|
cluster: restic
|
||||||
|
# --8<-- [end:cluster_route]
|
||||||
|
http_filters:
|
||||||
|
# --8<-- [start:rbac]
|
||||||
|
- name: envoy.filters.http.rbac
|
||||||
|
typed_config:
|
||||||
|
"@type": type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC
|
||||||
|
rules:
|
||||||
|
action: ALLOW
|
||||||
|
policies:
|
||||||
|
"ubuntu-policy":
|
||||||
|
permissions:
|
||||||
|
- and_rules:
|
||||||
|
rules:
|
||||||
|
- header:
|
||||||
|
name: ":path"
|
||||||
|
string_match:
|
||||||
|
prefix: "/john-ubuntu"
|
||||||
|
principals:
|
||||||
|
- authenticated:
|
||||||
|
principal_name:
|
||||||
|
exact: "spiffe://john-stream.com/ubuntu"
|
||||||
|
"p14-policy":
|
||||||
|
permissions:
|
||||||
|
- and_rules:
|
||||||
|
rules:
|
||||||
|
- header:
|
||||||
|
name: ":path"
|
||||||
|
string_match:
|
||||||
|
prefix: "/john-p14s"
|
||||||
|
principals:
|
||||||
|
- authenticated:
|
||||||
|
principal_name:
|
||||||
|
exact: "spiffe://john-stream.com/john-p14s"
|
||||||
|
"gitea-policy":
|
||||||
|
permissions:
|
||||||
|
- and_rules:
|
||||||
|
rules:
|
||||||
|
- header:
|
||||||
|
name: ":path"
|
||||||
|
string_match:
|
||||||
|
prefix: "/gitea"
|
||||||
|
principals:
|
||||||
|
- authenticated:
|
||||||
|
principal_name:
|
||||||
|
exact: "spiffe://john-stream.com/gitea"
|
||||||
|
# --8<-- [end:rbac]
|
||||||
|
- name: envoy.filters.http.router
|
||||||
|
typed_config:
|
||||||
|
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
|
||||||
|
# --8<-- [start:cluster]
|
||||||
|
clusters:
|
||||||
|
- name: restic
|
||||||
|
connect_timeout: 0.25s
|
||||||
|
type: STRICT_DNS
|
||||||
|
lb_policy: ROUND_ROBIN
|
||||||
|
load_assignment:
|
||||||
|
cluster_name: restic
|
||||||
|
endpoints:
|
||||||
|
- lb_endpoints:
|
||||||
|
- endpoint:
|
||||||
|
address:
|
||||||
|
socket_address:
|
||||||
|
address: rest-server
|
||||||
|
port_value: 8000
|
||||||
|
# --8<-- [end:cluster]
|
||||||
@@ -22,9 +22,9 @@ print_status() {
|
|||||||
|
|
||||||
EXIT_CODE=0
|
EXIT_CODE=0
|
||||||
|
|
||||||
CERTS_DIR="$(readlink -f ~/.step/certs)"
|
CERTS_DIR="/var/lib/tls"
|
||||||
SERVER_CERT="$CERTS_DIR/restic.crt"
|
SERVER_CERT="$CERTS_DIR/cert.pem"
|
||||||
SERVER_KEY="$CERTS_DIR/restic.key"
|
SERVER_KEY="$CERTS_DIR/key.pem"
|
||||||
TIMER_NAME="cert-renewer.timer"
|
TIMER_NAME="cert-renewer.timer"
|
||||||
|
|
||||||
# 1. Check Certificates Existence
|
# 1. Check Certificates Existence
|
||||||
|
|||||||
Reference in New Issue
Block a user