Self-host end-to-end encrypted contacts, calendars, tasks and notes with EteSync container

EteSync is easy to use end-to-end encrypted sync for your contacts, calendars, tasks and notes. It seamlessly integrates with your existing apps so you won't even notice you are using it.

It is also easy to self-host, which we will do in a rootless podman container using victorrds/etesync image.

  1. Prepare directory where service data will be stored, e.g. /srv/etesync:

    sudo mkdir -p /srv/etesync
    sudo chown -R $USER:$USER /srv/etesync
    
  2. Run EteSync container:

    podman run \
    --name etesync \
    -e SUPER_USER=admin \
    -e SERVER=http \
    -p 127.0.0.1:3735:3735 \
    -v /srv/etesync/data:/data:U \
    -v /srv/etesync/static:/srv/etebase/static:U \
    docker.io/victorrds/etesync:alpine
    
    Here's what exactly will happen

    Podman will download and run victorrds/etesync container with the following settings:

    • Container will be named etesync (--name arg)
    • Admin account named admin will be created on the first run (-e SUPER_USER arg)
    • Web app will be served on http://127.0.0.1:3735 (-e SERVER and -p args)
    • Web app static assets will be stored in /srv/etesync/static (-v arg)
    • Data will be saved to /srv/etesync/data (-v arg)

    For more info on this container and its configuration see github.com/victor-rds/docker-etebase

  3. On the first run it will create admin user and password, please note it from run log, e.g.:

    Admin Password: WQtqL10QHU7Dau4r10UGAbAYHl6Gb5eg
    
  4. Configure your web server to listen on domain of your choice, e.g. etesync.example.com and proxy requests to EteSync on http://127.0.0.1:3735. I use Nginx with the following config:

    /etc/nginx/conf.d/etesync.example.com.conf
    server {
      listen 80;
      listen [::]:80;
      server_name etesync.example.com;
      return 301 https://$host$request_uri;
    }
    
    server {
      listen 443 ssl http2;
      listen [::]:443 ssl http2;
    
      server_name etesync.example.com;
    
      ssl_certificate /etc/letsencrypt/live/etesync.example.com/fullchain.pem;
      ssl_certificate_key /etc/letsencrypt/live/etesync.example.com/privkey.pem;
      ssl_trusted_certificate /etc/letsencrypt/live/etesync.example.com/fullchain.pem;
    
      charset utf-8;
    
      location / {
        proxy_pass http://127.0.0.1:3735;
    
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $server_name;
      }
    
      location /static/ {
        autoindex on;
        alias /srv/etesync/static/;
      }
    
      location /user-media/ {
        autoindex on;
        alias /srv/etesync/data/media/;
      }
    
      location /.well-known/ {
        alias /var/www/etesync.example.com/.well-known/;
      }
    
      location = /favicon.ico {
        log_not_found off;
        access_log off;
      }
    
      location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
      }
    }
    
  5. Log in to admin interface at etesync.example.com/admin with admin user and password (see step 3) and create regular users as needed. No need to set passwords, users will set password themselves on first login.

  6. That's it! 🥳
    Users can now log in and use your EteSync instance via mobile or desktop apps, see EteSync user guide.

  7. One last thing, though 😁
    You probably want to autostart EteSync container on system start. Use systemd user service for that:

    • Enable user to start a service at system start and persist over logouts:

      sudo loginctl enable-linger $USER
      
    • Create directory for user's systemd units:

      mkdir -p ~/.config/systemd/user
      
    • Create systemd unit for EteSync container:

      podman generate systemd --name etesync > ~/.config/systemd/user/container-etesync.service
      
    • Enable it:

      systemctl enable --now --user container-etesync
      
    • Restart it to test if it's working properly:

      systemctl restart --user container-etesync
      
    • In case case something goes wrong, see logs:

      journalctl --user -xeu container-etesync