User Tools

Site Tools


computing:ente

This is an old revision of the document!



  • 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 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

## 1. Base system 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

## 2. Go, Rust, Node

sudo apt install -y golang-go rustup nodejs npm
rustup default stable
go version
rustc --version
node -v
npm -v

### 3. PostgreSQL

Create the db with sudo -u postgres psql and something like:

```sql 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:

```bash 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;' ``` ## 4. Museum binary + yaml config Run the go setup bits and migrate the example yaml config to production so we can edit params:

```bash 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 (keys from the generator, DB, then S3 after Garage). Do not regenerate keys on a live database. Create systemd unit.

```bash 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 ``` ## 5. Web app building and migrating content from repo

```bash 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 ```

## 6. Caddy reverse proxy, acme certs, load balancing, vhosts, etc.

nano `/etc/caddy/Caddyfile`:

Then,

```caddy {

  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:

```bash 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

## 7. First user 1. Open https://gnulinux.pics and sign up. 2. OTP: `journalctl -u ente-museum -n 200 –no-pager` 3. User id: ```bash

You need to locate the id# by searching logs for your email in close proximity. Or, 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:

```yaml internal:

  admins:
      - USER_ID
  trusted-client-ip-header: X-Forwarded-For

```

Restart service,

```bash sudo systemctl restart ente-museum ``` How to edit admin user to give them more storage:

```bash 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.

```bash 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:

```bash 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.

```yaml 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

```bash sudo systemctl restart ente-museum ```

### Draft Upgrade Garage Steps

```bash 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:

```bash 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.

## 9. museum.yaml example config layout for base setup

```yaml 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

```

## 10. Draft update sequence

```bash 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

oemb1905 2026/09/21 02:27

computing/ente.1789959017.txt.gz · Last modified: by oemb1905