feat(chhoto): add url shortener service

Integrates the chhoto-url shortener as a new service.
This includes its NixOS module, SOPS secrets, and Traefik routing.
This commit is contained in:
2026-03-19 11:29:43 +01:00
parent dcb03c97c1
commit bde897aced
4 changed files with 74 additions and 3 deletions
+1
View File
@@ -141,6 +141,7 @@
./services/vaultwarden
./services/nextcloud
./services/pangolin
./services/chhoto
# ./services/stalwart
];
};
+4 -3
View File
@@ -6,6 +6,7 @@ nextcloud_user: ENC[AES256_GCM,data:TKLOVc+5EW/9,iv:iuLuhBHJb0gW5NbWNCSHBxXxFYLh
nextcloud_password: ENC[AES256_GCM,data:dq1NL4UaHg/6Qqzn8bZ3W/ZN+A==,iv:6GzEcrdADi6+4Wqb8T2aI6+o3MQuwQpP4wsmDs7oMRY=,tag:XdQF3w2o1Sqx13GVsg0PFA==,type:str]
nextcloud_admin_user: ENC[AES256_GCM,data:ZH4BYQ==,iv:OiLCzzXC8pfAnpyTFuNkFMvBk3+EdtlTPw68sKW6mEo=,tag:jgr9y16mra2jOcOHa6HAlw==,type:str]
nextcloud_admin_password: ENC[AES256_GCM,data:Ctm/q5NL4eyiK8qa25E7i/FO0g==,iv:4tWa9Ai1HpQAS/ZcNAsm8U0XjDV0t7zKOPNHkG9ezOY=,tag:sqW+rzRG6I8YpsQ76raEiA==,type:str]
chhoto_env: ENC[AES256_GCM,data:v8J24PT3H6WMNogx25gNkp/WQTCBONeCSDum4wv8fwC9xnCbF4E/8Zf28uXfA4CBP/jxpvmnhWiWyZmK7OMCs1AYBWQTQSxmvYh9hGK0ZkQT0TTKwGabl/A31QVclR8RA6c6D3kA4MBUBmBJAqUlzGYkXHImmmMJNKm/9wzdm8alrE+aI4pwBqaAzsZWf7CWX/3MbnQZn5p/tuGY3AEVnwMbMx6Jcvog,iv:Kvcp2+axFQVtNSm/033g8TvVWkLJNt03wVKOMGKPoe0=,tag:FpxIOOyCQ/NwAZ3vkdP1CQ==,type:str]
sops:
age:
- recipient: age13tc3mtr45glx0msgsygf8zc3dh9kaxcestdx8uhzztpy0mawhems4l0wsz
@@ -35,7 +36,7 @@ sops:
cWh4Z3c3UWRNRG40TkxCTzRKOHZ2eDAK8ElreFdNPiDNrMCipQzi/hjk2alyD738
0ia0DbiriLVDSyTrDc4BwsW1TvR2Vn0o+erjEfU4PaCF8MLH4SJxJw==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2026-02-03T23:20:23Z"
mac: ENC[AES256_GCM,data:V8i0zQIrAve+Z+oaUP25k/aiK05qVUcZp8pDAFAfz0ymYfaANwjDkWcesEHnxYjScpVssiLB3CsjX2/oeTmWApyrTdLwEwbZ8iqUpSPb61kyWJ73O0uFdqBVe6XKr6LfyK6w9ekmSrAjwwI+xa88ZsLHzdqUsS2DaqCtkPridv4=,iv:FIoceU5ml7p27InS1BD4MUoGbiJ9d+nx9oGVPuJ9K9U=,tag:scR6j5kKsz5XcFb3k+Xv/g==,type:str]
lastmodified: "2026-03-19T10:29:20Z"
mac: ENC[AES256_GCM,data:A9scjoDNaKLDaVTGZYYZzQRBCBG5/jvZLM4GLWzsY5I0gHaJXw8QcrJJQF1KK/amD0eMifbIo+pnHeg8gMt70KRr9yQFyxbdor8vZPXGEHuhdbUl1RJ2brvypGH+vW2XEd9He8LHK7K4tavl5Q+/mRnQdpi6PCoYk5m2fLyNzcw=,iv:AbLUhWuKO+1YEuaj9wT6/HE9unF91dM56hwWz7bBlC4=,tag:9pE7jYMf9AfMLov6eQDI5g==,type:str]
unencrypted_suffix: _unencrypted
version: 3.11.0
version: 3.12.1
+60
View File
@@ -0,0 +1,60 @@
{config, ...}: {
# ── Secrets via SOPS ────────────────────────────────────────────
# Dans ton anywhere.yml, ajoute :
# chhoto_env: |
# password=un_mot_de_passe_fort
# api_key=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 128)
sops.secrets."chhoto/env" = {
key = "chhoto_env";
};
# ── Répertoire persistant (SQLite + WAL side-files) ─────────────
# WAL mode requiert un dossier entier monté, pas un fichier seul
systemd.tmpfiles.rules = [
"d /var/lib/chhoto 0750 root root -"
];
# ── Container ───────────────────────────────────────────────────
virtualisation.podman = {
enable = true;
dockerCompat = true;
defaultNetwork.settings.dns_enabled = true;
};
virtualisation.oci-containers.backend = "podman";
virtualisation.oci-containers.containers.chhoto-url = {
image = "sintan1729/chhoto-url:latest";
autoStart = true;
ports = ["127.0.0.1:4567:4567"];
volumes = ["/var/lib/chhoto:/data"];
environment = {
db_url = "/data/urls.sqlite";
use_wal_mode = "True";
site_url = "https://s.vps.marcpartensky.com";
redirect_method = "PERMANENT";
slug_style = "UID";
slug_length = "8";
try_longer_slug = "True";
port = "4567";
};
# Le fichier SOPS déchiffré contient password= et api_key=
environmentFiles = [config.sops.secrets."chhoto/env".path];
extraOptions = [
"--pull=newer"
"--health-cmd=curl -sf http://localhost:4567/ || exit 1"
"--health-interval=30s"
"--health-timeout=5s"
"--health-retries=3"
];
};
systemd.services."podman-chhoto-url" = {
after = ["network-online.target"];
wants = ["network-online.target"];
};
}
+9
View File
@@ -52,3 +52,12 @@
entryPoints = ["websecure"]
service = "stalwart"
tls = { certResolver = "letsencrypt" }
[http.services.chhoto.loadBalancer]
[[http.services.chhoto.loadBalancer.servers]]
url = "http://127.0.0.1:4567"
[http.routers.chhoto]
rule = "Host(`s.vps.marcpartensky.com`)"
entryPoints = ["websecure"]
service = "chhoto"
tls = { certResolver = "letsencrypt" }