feat(atlas): deploy self-hosted honcho
This commit is contained in:
@@ -39,6 +39,7 @@
|
||||
outline = 3019;
|
||||
authentik = 3023;
|
||||
tuwunel = 3024;
|
||||
honcho = 3025;
|
||||
|
||||
# Home automation
|
||||
homarr = 7575;
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
secrets = {
|
||||
baserow-env = {file = ../../secrets/baserow-env.age;};
|
||||
ghost-env = {file = ../../secrets/ghost-env.age;};
|
||||
honcho-selfhost-db-password = {
|
||||
file = ../../secrets/honcho-selfhost-db-password.age;
|
||||
owner = "postgres";
|
||||
group = "postgres";
|
||||
mode = "400";
|
||||
};
|
||||
honcho-selfhost-env = {file = ../../secrets/honcho-selfhost-env.age;};
|
||||
honcho-selfhost-jwt-secret = {file = ../../secrets/honcho-selfhost-jwt-secret.age;};
|
||||
kestra-config = {
|
||||
file = ../../secrets/kestra-config.age;
|
||||
mode = "644";
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
imports = [
|
||||
./baserow.nix
|
||||
./ghost.nix
|
||||
./honcho.nix
|
||||
./kestra.nix
|
||||
./littlelink.nix
|
||||
./matomo.nix
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
serviceName = "honcho";
|
||||
image = "ghcr.io/plastic-labs/honcho:v3.0.6";
|
||||
|
||||
apiIp = "10.89.0.24";
|
||||
deriverIp = "10.89.0.25";
|
||||
redisIp = "10.89.0.26";
|
||||
|
||||
postgresHost = "10.89.0.1";
|
||||
postgresPort = config.m3ta.ports.get "postgres";
|
||||
honchoPort = config.m3ta.ports.get "honcho";
|
||||
|
||||
# m3-atlas Netbird mesh address, discovered from `netbird status -d`.
|
||||
# Binding the host port here keeps self-hosted Honcho off public interfaces.
|
||||
netbirdBindAddress = "100.81.142.56";
|
||||
netbirdRange = "100.64.0.0/16";
|
||||
|
||||
dbName = "honcho";
|
||||
dbUser = "honcho";
|
||||
redisName = "${serviceName}-redis";
|
||||
runtimeDirectory = "/run/${serviceName}";
|
||||
runtimeEnvFile = "${runtimeDirectory}/env";
|
||||
|
||||
# Keep auth disabled for the first deployment because Honcho clients need
|
||||
# generated JWTs. The JWT secret is still provisioned so enabling auth later is
|
||||
# a one-line change here plus client token generation.
|
||||
authUseAuth = false;
|
||||
|
||||
sharedEnvironment = {
|
||||
CACHE_ENABLED = "true";
|
||||
CACHE_URL = "redis://${redisName}:6379/0?suppress=true";
|
||||
LOG_LEVEL = "INFO";
|
||||
TELEMETRY_ENABLED = "false";
|
||||
VECTOR_STORE_MIGRATED = "false";
|
||||
VECTOR_STORE_TYPE = "pgvector";
|
||||
AUTH_USE_AUTH = lib.boolToString authUseAuth;
|
||||
};
|
||||
|
||||
sharedEnvironmentFiles = [
|
||||
runtimeEnvFile
|
||||
config.age.secrets."${serviceName}-selfhost-env".path
|
||||
];
|
||||
|
||||
webNetwork = ip: [
|
||||
"--add-host=postgres:${postgresHost}"
|
||||
"--network=web:ip=${ip}"
|
||||
];
|
||||
|
||||
# The shared web network is intentionally internal. API and deriver also join
|
||||
# this egress-only network so LLM provider calls can leave the host without
|
||||
# exposing any extra inbound ports.
|
||||
networksWithEgress = ip:
|
||||
(webNetwork ip)
|
||||
++ [
|
||||
"--network=${serviceName}-egress"
|
||||
];
|
||||
|
||||
apiHealthCmd = ''/app/.venv/bin/python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health', timeout=2).read()"'';
|
||||
in {
|
||||
system.activationScripts.createPodmanNetworkHonchoEgress = lib.mkAfter ''
|
||||
if ! /run/current-system/sw/bin/podman network exists ${serviceName}-egress; then
|
||||
/run/current-system/sw/bin/podman network create ${serviceName}-egress
|
||||
fi
|
||||
'';
|
||||
|
||||
virtualisation.oci-containers.containers = {
|
||||
"${serviceName}-redis" = {
|
||||
image = "docker.io/redis:8.2";
|
||||
autoStart = true;
|
||||
volumes = ["${serviceName}_redis_data:/data"];
|
||||
extraOptions =
|
||||
(webNetwork redisIp)
|
||||
++ [
|
||||
"--health-cmd=redis-cli ping"
|
||||
"--health-interval=5s"
|
||||
"--health-timeout=5s"
|
||||
"--health-retries=5"
|
||||
];
|
||||
};
|
||||
|
||||
"${serviceName}-api" = {
|
||||
inherit image;
|
||||
autoStart = true;
|
||||
entrypoint = "sh";
|
||||
cmd = ["docker/entrypoint.sh"];
|
||||
environment = sharedEnvironment;
|
||||
environmentFiles = sharedEnvironmentFiles;
|
||||
ports = ["${netbirdBindAddress}:${toString honchoPort}:8000"];
|
||||
dependsOn = [redisName];
|
||||
extraOptions =
|
||||
(networksWithEgress apiIp)
|
||||
++ [
|
||||
"--health-cmd=${apiHealthCmd}"
|
||||
"--health-interval=5s"
|
||||
"--health-timeout=5s"
|
||||
"--health-retries=5"
|
||||
"--health-start-period=10s"
|
||||
];
|
||||
};
|
||||
|
||||
"${serviceName}-deriver" = {
|
||||
inherit image;
|
||||
autoStart = true;
|
||||
entrypoint = "/app/.venv/bin/python";
|
||||
cmd = ["-m" "src.deriver"];
|
||||
environment = sharedEnvironment;
|
||||
environmentFiles = sharedEnvironmentFiles;
|
||||
dependsOn = ["${serviceName}-api" redisName];
|
||||
extraOptions = networksWithEgress deriverIp;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services = {
|
||||
"${serviceName}-postgres-bootstrap" = {
|
||||
description = "Bootstrap Honcho PostgreSQL role, database, password, and pgvector";
|
||||
after = ["postgresql.service" "agenix.service"];
|
||||
requires = ["postgresql.service" "agenix.service"];
|
||||
before = ["${serviceName}-env.service" "podman-${serviceName}-api.service" "podman-${serviceName}-deriver.service"];
|
||||
requiredBy = ["podman-${serviceName}-api.service" "podman-${serviceName}-deriver.service"];
|
||||
path = [
|
||||
config.services.postgresql.package
|
||||
pkgs.coreutils
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "postgres";
|
||||
Group = "postgres";
|
||||
};
|
||||
script = ''
|
||||
set -euo pipefail
|
||||
test -s ${config.age.secrets."${serviceName}-selfhost-db-password".path}
|
||||
|
||||
psql -v ON_ERROR_STOP=1 --dbname=postgres <<'SQL'
|
||||
DO $$
|
||||
BEGIN
|
||||
CREATE ROLE ${dbUser} LOGIN;
|
||||
EXCEPTION WHEN duplicate_object THEN
|
||||
NULL;
|
||||
END
|
||||
$$;
|
||||
|
||||
SELECT 'CREATE DATABASE ${dbName} OWNER ${dbUser}'
|
||||
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '${dbName}')\gexec
|
||||
|
||||
ALTER DATABASE ${dbName} OWNER TO ${dbUser};
|
||||
\set honcho_password `cat ${config.age.secrets."${serviceName}-selfhost-db-password".path}`
|
||||
ALTER ROLE ${dbUser} WITH LOGIN PASSWORD :'honcho_password';
|
||||
SQL
|
||||
|
||||
psql -v ON_ERROR_STOP=1 --dbname=${dbName} <<'SQL'
|
||||
CREATE EXTENSION IF NOT EXISTS vector;
|
||||
GRANT ALL PRIVILEGES ON DATABASE ${dbName} TO ${dbUser};
|
||||
SQL
|
||||
'';
|
||||
};
|
||||
|
||||
"${serviceName}-env" = {
|
||||
description = "Generate Honcho runtime environment file with agenix secrets";
|
||||
after = ["agenix.service" "${serviceName}-postgres-bootstrap.service"];
|
||||
requires = ["agenix.service" "${serviceName}-postgres-bootstrap.service"];
|
||||
before = ["podman-${serviceName}-api.service" "podman-${serviceName}-deriver.service"];
|
||||
requiredBy = ["podman-${serviceName}-api.service" "podman-${serviceName}-deriver.service"];
|
||||
path = [
|
||||
pkgs.coreutils
|
||||
pkgs.python3
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
set -euo pipefail
|
||||
install -d -m 0750 ${runtimeDirectory}
|
||||
|
||||
db_password_encoded=$(
|
||||
python3 -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.stdin.read().strip(), safe=""))' \
|
||||
< ${config.age.secrets."${serviceName}-selfhost-db-password".path}
|
||||
)
|
||||
jwt_secret=$(tr -d '\r\n' < ${config.age.secrets."${serviceName}-selfhost-jwt-secret".path})
|
||||
|
||||
umask 077
|
||||
cat > ${runtimeEnvFile} <<ENV
|
||||
DB_CONNECTION_URI=postgresql+psycopg://${dbUser}:$db_password_encoded@postgres:${toString postgresPort}/${dbName}
|
||||
AUTH_JWT_SECRET=$jwt_secret
|
||||
ENV
|
||||
'';
|
||||
};
|
||||
|
||||
"podman-${serviceName}-api" = {
|
||||
after = ["${serviceName}-env.service" "${serviceName}-postgres-bootstrap.service"];
|
||||
requires = ["${serviceName}-env.service" "${serviceName}-postgres-bootstrap.service"];
|
||||
};
|
||||
|
||||
"podman-${serviceName}-deriver" = {
|
||||
after = ["${serviceName}-env.service" "${serviceName}-postgres-bootstrap.service"];
|
||||
requires = ["${serviceName}-env.service" "${serviceName}-postgres-bootstrap.service"];
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.extraCommands = ''
|
||||
# Self-hosted Honcho API: only Netbird mesh peers may reach ${netbirdBindAddress}:${toString honchoPort}.
|
||||
ip46tables -A nixos-fw -p tcp --dport ${toString honchoPort} -s ${netbirdRange} -j nixos-fw-accept
|
||||
'';
|
||||
}
|
||||
@@ -28,6 +28,7 @@
|
||||
host kestra kestra 10.89.0.0/24 scram-sha-256
|
||||
host netbird netbird 10.89.0.0/24 scram-sha-256
|
||||
host authentik authentik 10.89.0.0/24 scram-sha-256
|
||||
host honcho honcho 10.89.0.0/24 scram-sha-256
|
||||
|
||||
# Deny all other connections
|
||||
local all all reject
|
||||
@@ -38,7 +39,7 @@
|
||||
services.postgresqlBackup = {
|
||||
enable = true;
|
||||
startAt = "03:10:00";
|
||||
databases = ["baserow" "paperless" "kestra" "authentik" "netbird"];
|
||||
databases = ["baserow" "paperless" "kestra" "authentik" "netbird" "honcho"];
|
||||
};
|
||||
networking.firewall = {
|
||||
extraCommands = ''
|
||||
|
||||
@@ -38,6 +38,9 @@ in {
|
||||
"secrets/basecamp-client-id.age".publicKeys = systems ++ users;
|
||||
"secrets/basecamp-client-secret.age".publicKeys = systems ++ users;
|
||||
"secrets/gitea-runner-token.age".publicKeys = systems ++ users;
|
||||
"secrets/honcho-selfhost-db-password.age".publicKeys = systems ++ users;
|
||||
"secrets/honcho-selfhost-env.age".publicKeys = systems ++ users;
|
||||
"secrets/honcho-selfhost-jwt-secret.age".publicKeys = systems ++ users;
|
||||
"secrets/outline-key.age".publicKeys = systems ++ users;
|
||||
"secrets/restreamer-env.age".publicKeys = systems ++ users;
|
||||
"secrets/searx.age".publicKeys = systems ++ users;
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IDVrd2NzQSBJV1Fa
|
||||
U2gzWjJKOHlsK202dXAzVENFdmZ5ZmJsc01STnRnTWMvdjFyZ21NCjU5Q0hwbVlV
|
||||
dVlRTUZDb0JESHBaTzk5ancrTWNpLzYrMFk2QWU0Z0EvUmsKLT4gc3NoLWVkMjU1
|
||||
MTkgM0JjcjF3IEdia0tSQTZWcEE3ODE4VjU2M0ZGay9rbXlzbFNqZWxpb1lGSExw
|
||||
RW5keGsKWDlwRzcwT1BaTDByT0R6T3hqWTE1UWVyN2xhSzhSMlhBdW5FakNjZ1Ux
|
||||
NAotPiBzc2gtZWQyNTUxOSA5ZDRZSVEgcnNJRnA2SVVkMHRXZTErc0VFbmduMDBz
|
||||
ZkQzK3dMQ2xadkMyYllhOE1rOAprWmg4T3RiaTF5QXdmRGUxVDVpVnZWdWxRYTJv
|
||||
WGVUQUhsT0VjKzl0NnJrCi0+IHNzaC1lZDI1NTE5IDROTEtydyAvc1ZTc0hRd3R4
|
||||
V2U4dEpaeEZEZlVyc2ZHSlNiVSt3T1M3bndsVXpPNkhVCmt2WlplcVcza2YxV05T
|
||||
bnRIOWpMYWpxck5jSzRtQVZ2L2ZQS3J1VjVTWDgKLT4gc3NoLWVkMjU1MTkgYzRO
|
||||
UWxBIHZCKzR5RXN2RmYvc3ZPTGJRRG1peUN6bmNuVFpSd2NPdWJwTTJYdHllRW8K
|
||||
TEo4QUI1a3ZzQ3NSQldSN1lTMlVwVGhTcTRPaHpYVHZVdHowYmZqR1czVQotPiBz
|
||||
c2gtcnNhIERRbEU3dwpvRzJjS0h3b2p4RXJrSDI1VEszQ1BvckNUS2laV3hGVVlx
|
||||
TXd0VkcvQ1hvWElNWnVNa1JoeHhMTDFUUWZnV0YxCjNHajRtZ0lmQzVXZmhyM1Nq
|
||||
SWoyVTFFdmowNTdZV0J0WHE5cXdZb2U1OVJOb1hYb1lnSjdqN09Bd2IvOUFlckMK
|
||||
d3hBc3pUK1J2Y3VnTjNSR0Q0cVJUVlluNllBazJ2L1dmOXVvZXI0WjVYbjI1RXhr
|
||||
Rm1EMzkxcStrYWRJTFNJKwo3YjZ6MEZ3RmtLZytiWGdBWWZEYU9EQWxEZWtzV3dD
|
||||
dGhJUUd0ajcvUFlxVGJqTVhlWmhSeHpkMHQyWWs5ZS9DClNEV0gzcWM2YlJTQ1lM
|
||||
bE4zTFJKSFU1VjAybFJvY1FQR2tNSFo2NFVDczBTUW9UWjY4aDVNUzlYaVlkdzJm
|
||||
dUsKckVaVld4YXpsdGYwWHVrWEtTbDJBU2cwcXlJSGY4ZEhlT2o4QlRBVGxWRHNL
|
||||
OXlMTGp5b1ZWbnJYV2pzaFFIcApQVmJzVi9kWnRpeWcyaS9weVN3SncxQjhlanBV
|
||||
dW5FU0VtL2lpS0NSTWtoOVI4akxXOUlhWW5xMkp2SUszSU9QCk1rZVdoNkI5TGRB
|
||||
L2twWWpPYVlSWUxrRElRcjhHMFczM29lcWlWWlJhbk0vcGFEQmw3UGdXWXJBNXJV
|
||||
VURYcFQKCi0+IHNzaC1lZDI1NTE5IENTTXloZyBpOEE3YUFzcytOYndXWWNreThp
|
||||
ZEdveGFlbHlPa0FwZ2xBY0lCcmIycTM4CnI0ZE1DM2d1bzZPV3diL2lZQi9SUnB1
|
||||
UWFjVVFueTFpMzRINm9Ob0pZMTQKLS0tIFJwZy9uRklOUEl0Z2hDNmx1YWsyNVov
|
||||
aHZ5VVhtMnVyYTMwbCtkaFFtR28KZzkT96InPG4YYyVKq0ZOrIBPtCJBbTXUJu+8
|
||||
9G03diIRwzYb6cSBRMtKKGl5NEfbJE7B2OnXeHPeCIPiGArKudKxFg9COHGOUP0h
|
||||
hUDDL9RGVhd4sMs8zRkxNghRwQzD
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
@@ -0,0 +1,30 @@
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IDVrd2NzQSBKZllV
|
||||
QytCeGYyVmtRMUxudm5iWmF3aWdITlRQVE53RnhFNUFabXkwbkg0CkE5Wk1mbXdm
|
||||
TzRuQTdvNklORUdSdHFIZm1zSVdvMWVnWWpRTUxDSzFBMHcKLT4gc3NoLWVkMjU1
|
||||
MTkgM0JjcjF3IDlISlRMdC9Sc2hic3JRV1o0WDNsbzByNmdFNnZDdjJSLytEa0xS
|
||||
VzRzQ2sKYXJGSjJDa2xuYThLNnhIMFhwTTNUSHJWbnFFYzZSRFQxVlVWK2xjNWgv
|
||||
dwotPiBzc2gtZWQyNTUxOSA5ZDRZSVEgaGUweXhJZmhTOGt3VFQ2R04rQjNOckxx
|
||||
c3BCMTBWZ0lsQmU3NmlVRkRYWQp6QlMvQkZmemVjekdLVWlDTUlNRG04MTlzaHAz
|
||||
cW9xd2JjNlE0eFF4NzNvCi0+IHNzaC1lZDI1NTE5IDROTEtydyBWQ2FGUCtFQ2FZ
|
||||
Wk5uSzZyTDNBTHRPUTkvTlRWR0Q1bHdqRjBycmU0VFc0CkdpSUNZZGw1aGJwUVk0
|
||||
VnlIR2IxVTJNaFVSNHJQSDR2YWxuN2ZiSERQSUEKLT4gc3NoLWVkMjU1MTkgYzRO
|
||||
UWxBIHlDYUlJRGxabTZxSnNpTUNWUDRXWUtHa0h3Z3BYTlZkUEtkall1OUh1VzQK
|
||||
ZEQzSW5tM0xFdWd1a3hibXlxa0N2N2RlemUyMkplRW5CNFZHUCtTSEhWdwotPiBz
|
||||
c2gtcnNhIERRbEU3dwpoNE9FdlpHYXJFZVRYQnBZNFZPTUhLb3RDdWpNcWxtU2gv
|
||||
MVF5Tm1tdHBuK3NLQjBnM2JudFFwQVZnb0VpUUljCjhKQk5HQnVrY05yeU53QWhK
|
||||
MG9QUVN5M2NXUEw2eEhQajFmaHZ4cWpFaXcwd3ZrSzNRWFNRREl5bERac1Y2LzYK
|
||||
c3BDVXlvQ20xaUt4KzZVRkhiNU5TYkpsbGQraFdvM3RvSkFZRU54SUV4ZWNnVG0y
|
||||
VVR6Q2swV2RFeUZwNGZxdQoveVhYN3JXVXBpQzdxa1ZKVXROcXRDQXladml5c2ZD
|
||||
ZjFVSVRaUkZiRVlNUHA3bDg2ek9mcXJnVG9YYStza3BFCktzVXlyZHNCZ1BxYTBO
|
||||
TUt1T3ZYQmR2VjErdVpPWVBOVDlFZm14Ukp0dkdUamNxODZPNFNTMXNabzNWUzVT
|
||||
MHIKUkJocFBhNitCMzFkWUhyV29FU3RMWjkvMWNxbzJFbTBHb2NpbW9Cb1dheHhn
|
||||
Y0N6S2FIQ2NROWtqQm5ORWxtYwo1NnF2RVQybnY2Wm5CQlJZOXVTVVNLUGZIbWZh
|
||||
V2laZWFQaXhEaGdma3pIWnlSaFpjSlRqNHlRZGNiaWhsWXlYCi9UM0Z2MldUMW01
|
||||
ekZja1hLNXptaFVCVFN5UVVlRGh0L2wvekxEckNmNTJOTUdoUE9wRzFaNzhqQnpM
|
||||
dThmWDUKCi0+IHNzaC1lZDI1NTE5IENTTXloZyB5ZzV4Q1pIOGpBOEtUcG1rNVZB
|
||||
QjFPbEt0OThxNWl3V1VhRTV2RFVrUGhRCmpwSHpUTnhNdlRHMnRvYWk2emJlSlhJ
|
||||
aWwweUg5dG1rYmRMMEVDTVdHdnMKLS0tIHp6alVpN1IvQ2E5UEV0Zm1nQk53cWJQ
|
||||
WCtTN08wSXlCSktkaDlPRG9Wa0UKyLX9C4xDpcPIVFsimn4OmCWAKZ1IPxeSzgr0
|
||||
W6Shg1EWCeMm3dQVJ8O9mji4JW/SJHKwqlJvFTMPhIwcdIo=
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
@@ -0,0 +1,31 @@
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IDVrd2NzQSBTNk5O
|
||||
dmZTRnRnOU5JMHU4QitlWWMyaXhscm1aQWNQSWJmVjU3MHdvVmowClkrVTV6VVVV
|
||||
Q0tiWXlkcGtHS3AwTUtqYmJwdnowMXFLcGNYb1dVZmpVTGcKLT4gc3NoLWVkMjU1
|
||||
MTkgM0JjcjF3IGVpdFlFTUFZQS9IMzVaRkNHSHltcHV1QlFmYk1yRitvZjhZZzI2
|
||||
ZDlTR3MKQ0RKT0tWZ0JGOUZCMTk2bitENmxnZzc1VDloNktvaVJFdGxyaVFaMjhJ
|
||||
VQotPiBzc2gtZWQyNTUxOSA5ZDRZSVEgdmw1MTg1R3lLR1NFNGUzQXpnUS9TNjRq
|
||||
czVtYlFzUmJnbmJ1c3JFRVZCQQoyYzBmQzdPbFVyU3diWlNuc1JoaHptOTFCUFBX
|
||||
RFpDZk4rWHByOGp2bkJFCi0+IHNzaC1lZDI1NTE5IDROTEtydyBIZWdsejNPVkdZ
|
||||
dkN3Z1FLTkNCVTdKSHNIOGU4UUUwdklhS0oxMlc5ekVjCnNZL0ZsV1VMU1p0eEFp
|
||||
YzBOdndIRzB3KzZXNGRFaHBpVDQ4Wm1jb2E1Z1kKLT4gc3NoLWVkMjU1MTkgYzRO
|
||||
UWxBIGFteVpubkxhcm80VEllY1llYkx4YXRTRHU4clNwK1F1SWlMTWxtMTYvRncK
|
||||
YjhvRXBod2I5dUZaWGlyOHcwa3MvWjNPOCtKendiMk9zVE5mVlpTS1RVMAotPiBz
|
||||
c2gtcnNhIERRbEU3dwpoenRXZkF2ck1LWDhxK25ldG1HVmRzVEh4TVNuaTdwQmVW
|
||||
eW80TE5kYzd5YkFpZXZhdWVSdEh4VTA2TzhnMzNsCkZud1AvTUdWSHJtOWtEZzlj
|
||||
ai9SdG1PRUtCN3VWQXlyamVpV1dWTEZkaFZpZHIxQ0c0eHIva1dzeDN6MlJla24K
|
||||
dXcrNUxUWVdMTFpaRk1YbkszazNDdFhuSVdxbE9rVHNNWDBvbDF4WGlWT0d5RTJR
|
||||
WmxCSFAzbDVVNWJneWhJZApPVnozRkRsS2J2VkFRVEpDVWJicmhhWXA0eVEvZFEz
|
||||
eWtsY3ZaNEk1MzlDYVJDb09lZGRsVk9YMXhyOWJsNmJYCk5HRTRjb0RrdlRydjNs
|
||||
T3prdXMvbnF0Y0FlL0VUbHNuVzZPNWJSK09TdEpuVU83dytiUDJRbmpFazludkkz
|
||||
d3AKUUp6TkVWSWRHMkozR0lQR1JlNmZ5Nk05WkUwbWJaODUzNmJIVkNEazVRcFFO
|
||||
ZnVZengyeFhQSlFsbUlta0tPRwo5OURlRTlPNERLWlF6aE9QaS91T0kyb2tIS0kz
|
||||
L0FYNjhWVWp1Q2xqUVRialcyWkhXbTJwU0R5VmVkbE1GeGEyCmROTFErS2VsMEo1
|
||||
VHdta2RObmtwMWtJTzRuaEhRbTFFbEE0V1RKbUk3SCtLWlE1cHR5c09ncThxbVY1
|
||||
cnRETkUKCi0+IHNzaC1lZDI1NTE5IENTTXloZyBZbW1NSStwWGd5RE1kRkk5aTZX
|
||||
alZtUWk5M3pnU1ZTSFU5UExnS0d4NkcwCjAvblBmUG5MUVVTOEpncjJjY0I1QzN1
|
||||
eVVNMlVZenJ6MzVDRXFaMVgxREUKLS0tIFIwd1ZtanJuU0Q2Ym9kN3lSS1NtQlky
|
||||
NC93UWJXa0tXTUVON3NmNVpUR0kKX71fenkAzKU3aIHFjLTpemNxsc5unQTy9f1O
|
||||
jpfhFHRPG5HuUBtmi6Fuv2n8J8Gw70D0XKs6UgAYV5GY0Db1daJZRbgF9EExbadB
|
||||
JQm3DLy8LG6KAM250ooGHKJoJSfQ
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
Reference in New Issue
Block a user