------------------------------------------- * **ente** * **Jonathan Haack** * **Haack's Networking** * **webmaster@haacksnetworking.org** ------------------------------------------- //Ente// ------------------------------------------- This tutorial is for Debian users who want to setup Ente manually. I used this [[https://ente.com/help/self-hosting/installation/manual|tutorial]] as a jumping off point and setup Ente as documented below. Since minio is now paywalled, I used Garage as the s3-compat bucket and just pointed it at the vm's virtiofs mountpoint which points to underlying btrfs r10 on the host (encrypted w/ LUKS). Go / Node / Rust: * Go: ''apt install golang-go'' * Node/npm: ''apt install nodejs npm'' * Rust: ''apt install rustup'' then ''rustup default stable'' Addresses: * IPv4: ''8.28.86.133'' * IPv6: ''2604:fa40:0:10::36'' * Apex: ''gnulinux.pics'' DNS A/AAAA for: * gnulinux.pics * api.gnulinux.pics * s3.gnulinux.pics * albums.gnulinux.pics * accounts.gnulinux.pics * auth.gnulinux.pics * share.gnulinux.pics * cast.gnulinux.pics * embed.gnulinux.pics * memories.gnulinux.pics * legacy.gnulinux.pics Setup base system, sudo apt update && sudo apt upgrade -y sudo apt install -y ca-certificates curl wget git gnupg lsb-release build-essential pkg-config postgresql postgresql-contrib libsodium23 libsodium-dev caddy ufw sudo systemctl enable --now postgresql sudo ufw allow OpenSSH sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw enable git clone https://github.com/ente-io/ente.git /root/ente Now, Go, Rust, and Node setup: sudo apt install -y golang-go rustup nodejs npm rustup default stable go version rustc --version node -v npm -v Setup PostgreSQL and create the db with ''sudo -u postgres psql'' and something like: CREATE USER ente WITH ENCRYPTED PASSWORD 'ENTE_DB_PASS'; CREATE DATABASE ente_db OWNER ente; GRANT ALL PRIVILEGES ON DATABASE ente_db TO ente; \q Next, lock access to db: echo 'host ente_db ente 127.0.0.1/32 scram-sha-256' | sudo tee -a /etc/postgresql/*/main/pg_hba.conf echo 'host ente_db ente ::1/128 scram-sha-256' | sudo tee -a /etc/postgresql/*/main/pg_hba.conf sudo systemctl reload postgresql PGPASSWORD='ENTE_DB_PASS' psql -h 127.0.0.1 -U ente -d ente_db -c 'SELECT 1;' Edit museum.yaml and configure it, build its web apps, start it, and create unit: cd /root/ente/server go mod tidy go build cmd/museum/main.go go run tools/gen-random-keys/main.go cp config/example.yaml museum.yaml Edit ''/root/ente/server/museum.yaml'' using keys from second to last step above. Now, create systemd unit. sudo tee /etc/systemd/system/ente-museum.service >/dev/null << 'EOF' [Unit] Description=Ente Museum After=network-online.target postgresql.service Wants=network-online.target [Service] Type=simple WorkingDirectory=/root/ente/server ExecStart=/root/ente/server/main Restart=on-failure RestartSec=3 Environment=GIN_MODE=release [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable --now ente-museum curl -sS http://127.0.0.1:8080/ping Build the Web apps and migrating content from repo cd /root/ente/web npm ci export NEXT_PUBLIC_ENTE_ENDPOINT=https://api.gnulinux.pics npm run build npm run build:albums npm run build:accounts npm run build:auth npm run build:cast npm run build:share npm run build:embed npm run build:memories sudo mkdir -p /var/www/ente/apps sudo rm -rf /var/www/ente/apps/* sudo cp -a apps/photos/out /var/www/ente/apps/photos sudo cp -a apps/albums/out /var/www/ente/apps/albums sudo cp -a apps/accounts/out /var/www/ente/apps/accounts sudo cp -a apps/auth/out /var/www/ente/apps/auth sudo cp -a apps/cast/out /var/www/ente/apps/cast sudo cp -a apps/share/out /var/www/ente/apps/share sudo cp -a apps/embed/out /var/www/ente/apps/embed sudo cp -a apps/memories/out /var/www/ente/apps/memories sudo chown -R caddy:caddy /var/www/ente Setup Caddy reverse proxy / load balancer, acme certs, and vhosts with ''nano /etc/caddy/Caddyfile'' and enter the following: { email admin@gnulinux.pics } api.gnulinux.pics { reverse_proxy 127.0.0.1:8080 } gnulinux.pics { root * /var/www/ente/apps/photos encode gzip file_server try_files {path} {path}.html /index.html } albums.gnulinux.pics { root * /var/www/ente/apps/albums encode gzip file_server try_files {path} {path}.html /index.html } accounts.gnulinux.pics { root * /var/www/ente/apps/accounts encode gzip file_server try_files {path} {path}.html /index.html } auth.gnulinux.pics { root * /var/www/ente/apps/auth encode gzip file_server try_files {path} {path}.html /index.html } share.gnulinux.pics { root * /var/www/ente/apps/share encode gzip file_server try_files {path} {path}.html /index.html } cast.gnulinux.pics { root * /var/www/ente/apps/cast encode gzip file_server try_files {path} {path}.html /index.html } embed.gnulinux.pics { root * /var/www/ente/apps/embed encode gzip file_server try_files {path} {path}.html /index.html } memories.gnulinux.pics { root * /var/www/ente/apps/memories encode gzip file_server try_files {path} {path}.html /index.html } legacy.gnulinux.pics { root * /var/www/ente/apps/accounts encode gzip file_server try_files {path} {path}.html /index.html } s3.gnulinux.pics { header Access-Control-Allow-Origin * header Access-Control-Allow-Methods "GET, PUT, POST, HEAD, DELETE, OPTIONS" header Access-Control-Allow-Headers * header Access-Control-Expose-Headers "ETag, Accept-Ranges, Content-Range, Content-Length, Content-Type" header Access-Control-Max-Age 3600 @options method OPTIONS handle @options { respond 204 } reverse_proxy 127.0.0.1:3900 } Verify after making config, then restart service, debug as needed: sudo caddy validate --config /etc/caddy/Caddyfile sudo systemctl enable --now caddy sudo systemctl reload caddy curl -sS http://127.0.0.1:8080/ping curl -sSI https://gnulinux.pics curl -sS https://api.gnulinux.pics/ping End point works now, go to url in browser and create first user then use the id# to lock it as admin. - Open https://gnulinux.pics and sign up. - OTP: ''journalctl -u ente-museum -n 200 --no-pager'' - User id: 34982349839489320843 You need to locate the id# by searching logs for your email in close proximity as per above. Or, alternately, make a one-liner: journalctl -u ente-museum --no-pager | grep -F -A 80 'user@example.com' | grep -oE 'user_id=[1-9][0-9]*' | tail -1 Once that's done, go edit ''nano /root/ente/server/museum.yaml'': internal: admins: - USER_ID trusted-client-ip-header: X-Forwarded-For Restart service, sudo systemctl restart ente-museum How to edit admin user to give them more storage: PGPASSWORD='ENTE_DB_PASS' psql -h 127.0.0.1 -U ente -d ente_db -c "UPDATE subscriptions SET storage = 25::bigint * 1024 * 1024 * 1024 WHERE user_id = USER_ID RETURNING user_id, storage;" # 100 250 500 750 → same, change 25 # 1TB = 1024 1.5TB = 1536 2TB = 2048 ## 8. Garage (needed before uploads work) Warning: If you rerun layout/bucket/key it hoses the current bucket. sudo mkdir -p /var/lib/garage/meta /mnt/warehouse/media/glpics curl -fL -o /tmp/garage https://garagehq.deuxfleurs.fr/_releases/v2.4.1/x86_64-unknown-linux-musl/garage sudo install -m 0755 /tmp/garage /usr/local/bin/garage garage --version Create config .toml file and start garage service: sudo tee /etc/garage.toml >/dev/null << 'EOF' metadata_dir = "/var/lib/garage/meta" data_dir = "/mnt/warehouse/media/glpics" db_engine = "sqlite" replication_factor = 1 rpc_bind_addr = "127.0.0.1:3901" rpc_public_addr = "127.0.0.1:3901" rpc_secret = "GARAGE_RPC_SECRET" [s3_api] s3_region = "garage" api_bind_addr = "127.0.0.1:3900" root_domain = ".s3.gnulinux.pics" [admin] api_bind_addr = "127.0.0.1:3903" admin_token = "GARAGE_ADMIN_TOKEN" EOF Create systemd unit for garage to monitor and restart service: sudo tee /etc/systemd/system/garage.service >/dev/null << 'EOF' [Unit] Description=Garage S3 After=network-online.target Wants=network-online.target [Service] ExecStart=/usr/local/bin/garage -c /etc/garage.toml server Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable --now garage sudo systemctl status garage --no-pager Create bucket on the same host and name it / give perms for Ente's default s3-compatible endpoint: garage -c /etc/garage.toml status NODE=$(garage -c /etc/garage.toml node id -q | head -1) garage -c /etc/garage.toml layout assign -z dc1 -c 1T "$NODE" garage -c /etc/garage.toml layout apply --version 1 garage -c /etc/garage.toml bucket create b2-eu-cen garage -c /etc/garage.toml key create ente-photos garage -c /etc/garage.toml bucket allow b2-eu-cen --read --write --owner --key ente-photos garage -c /etc/garage.toml key info ente-photos Once the bucket is built, add the creds it spit out into ''/root/ente/server/museum.yaml'' and restart Museum. s3: are_local_buckets: false use_path_style_urls: true b2-eu-cen: key: GARAGE_ACCESS_KEY secret: GARAGE_SECRET_KEY endpoint: s3.gnulinux.pics region: garage bucket: b2-eu-cen Restart the service sudo systemctl restart ente-museum Draft Upgrade Garage Steps VER=v2.4.1 ARCH=x86_64-unknown-linux-musl curl -fL -o /tmp/garage "https://garagehq.deuxfleurs.fr/_releases/${VER}/${ARCH}/garage" /tmp/garage --version sudo systemctl stop ente-museum garage sudo cp -a /usr/local/bin/garage /usr/local/bin/garage.bak-$(date +%F) sudo install -m 0755 /tmp/garage /usr/local/bin/garage sudo systemctl start garage ente-museum garage -c /etc/garage.toml status curl -sS https://api.gnulinux.pics/ping Potential steps if garage upgrade fails: sudo systemctl stop garage sudo cp /usr/local/bin/garage.bak-YYYY-MM-DD /usr/local/bin/garage sudo systemctl start garage Do not layout/bucket/key on upgrade - it will hose current bucket. Example museum.yaml example config layout for base setup db: host: 127.0.0.1 port: 5432 name: ente_db user: ente password: ENTE_DB_PASS s3: are_local_buckets: false use_path_style_urls: true b2-eu-cen: key: GARAGE_ACCESS_KEY secret: GARAGE_SECRET_KEY endpoint: s3.gnulinux.pics region: garage bucket: b2-eu-cen apps: public-albums: https://albums.gnulinux.pics embed-albums: https://embed.gnulinux.pics public-locker: https://share.gnulinux.pics public-paste: https://share.gnulinux.pics cast: https://cast.gnulinux.pics accounts: https://accounts.gnulinux.pics public-memories: https://memories.gnulinux.pics legacy: https://gnulinux.pics key: encryption: MUSEUM_KEY_ENCRYPTION hash: MUSEUM_KEY_HASH jwt: secret: MUSEUM_JWT_SECRET internal: admins: - USER_ID trusted-client-ip-header: X-Forwarded-For smtp: host: mail.example.com port: 587 username: SMTP_USER password: SMTP_PASS email: SMTP_FROM sender-name: gnulinux.pics Draft update sequence sudo apt update && sudo apt upgrade rustup update cd /root/ente && git pull cd /root/ente/server go mod tidy go build cmd/museum/main.go sudo systemctl restart ente-museum cd /root/ente/web npm ci export NEXT_PUBLIC_ENTE_ENDPOINT=https://api.gnulinux.pics npm run build npm run build:albums npm run build:accounts npm run build:auth npm run build:cast npm run build:share npm run build:embed npm run build:memories sudo rsync -a --delete apps/photos/out/ /var/www/ente/apps/photos/ sudo rsync -a --delete apps/albums/out/ /var/www/ente/apps/albums/ sudo rsync -a --delete apps/accounts/out/ /var/www/ente/apps/accounts/ sudo rsync -a --delete apps/auth/out/ /var/www/ente/apps/auth/ sudo rsync -a --delete apps/cast/out/ /var/www/ente/apps/cast/ sudo rsync -a --delete apps/share/out/ /var/www/ente/apps/share/ sudo rsync -a --delete apps/embed/out/ /var/www/ente/apps/embed/ sudo rsync -a --delete apps/memories/out/ /var/www/ente/apps/memories/ sudo chown -R caddy:caddy /var/www/ente sudo systemctl reload caddy curl -sS https://api.gnulinux.pics/ping Store secrets properly --- //[[alerts@haacksnetworking.org|oemb1905]] 2026/09/21 02:50//