Host EventSlide yourself

EventSlide is free software: you can run it on your own machine, and your photos never leave it. This page is for people comfortable with a server. If that is not you, hosted access exists, and there is nothing to install.

See the commands Source code on GitHub

  • AGPL-3.0 licence
  • Signed Docker image
  • linux/amd64 and arm64
  • Your photos stay with you

Why host it yourself

Most party photo tools ask one of two things: that your guests install an app, or that you hand hundreds of family photos to a company you have never heard of. EventSlide asks for neither.

  • The photos stay with you

    EventSlide runs on a single machine: a laptop, a mini PC, a Raspberry Pi under the projector. Nothing leaves it.

  • You stay in charge

    You choose how long the album is kept, you back it up when you like, you delete it when you like. None of it depends on us.

  • Code you can read

    The code is public: you can check what the software does, change it, pass it on. The published image is signed and scanned with every release.

  • It lasts the night

    On a machine set up in the room, uploads are queued and retried and the wall keeps playing when the network drops. It can run on its own for an eight-hour evening.

What you need

  • A machine

    A laptop, a mini PC or a Raspberry Pi. The image exists for linux/amd64 and linux/arm64.

  • Docker

    With docker compose. Nothing is built on your machine: the published image is simply downloaded.

  • An https address the phones can reach

    It is the address the QR code holds (PUBLIC_URL). Never localhost: a QR code pointing at localhost is the most common way an install fails on the night. Scan your own QR code with your phone before the guests arrive.

  • A proxy that handles encryption (TLS)

    EventSlide speaks plain http and does not encrypt by itself. Something has to sit in front of it: Caddy, nginx or Traefik, whichever you already use. With Caddy, it is one line of configuration.

  • Node, to draw two secrets

    The commands below use it to generate two random secrets. Nothing else asks for it with Docker.

A venue with no domain name?

This case is not covered today. A machine on a local network, with no DNS and no certificate, cannot serve https that a guest’s phone will trust, and EventSlide does not run over plain http in production. The current answer: a real domain name pointed at the machine (it works over the venue’s Wi-Fi as long as the phones have a route to it), or a --network host proxy with a certificate you already own. For a fully offline wall, say so on the repository’s issue tracker.

Install with the signed Docker image

The image is published as ghcr.io/irony42/eventslide, for linux/amd64 and linux/arm64. It is signed and scanned with every release. The commands below are the ones in the repository’s README, word for word. When in doubt, the repository is the reference.

git clone https://github.com/Irony42/EventSlide.git
cd EventSlide

# Two secrets, and the address your guests' phones will reach.
node -e "console.log('SESSION_SECRET='+require('crypto').randomBytes(48).toString('base64url'))" >> .env
node -e "console.log('GUEST_TOKEN_SECRET='+require('crypto').randomBytes(48).toString('base64url'))" >> .env
echo "PUBLIC_URL=https://photos.example.com" >> .env
# Your own account, created on the first boot. The password is generated too, because
# one typed into a README is one everybody who read it could sign in with first.
echo "BOOTSTRAP_OWNER_EMAIL=you@example.com" >> .env
node -e "console.log('BOOTSTRAP_OWNER_PASSWORD='+require('crypto').randomBytes(18).toString('base64url'))" >> .env

docker compose up            # the first time, and read what it says
docker compose up -d         # once it has booted cleanly

What these commands do, and what is left for you

  1. Fetch the code and write the configuration

    The node commands draw two random secrets (SESSION_SECRET, GUEST_TOKEN_SECRET), then you note the address the phones will reach (PUBLIC_URL). The two BOOTSTRAP_OWNER lines create your account on first boot: there is no default admin and no setup page. The password is generated too, because one typed into a tutorial is the one everybody would try first.

  2. Run it in the foreground first

    The first up pulls the published image, at the version you checked out. A missing or malformed variable makes the server print every problem at once and exit. In the background the container restarts on its own and the list scrolls away. Once it boots cleanly, -d is the right way to leave it running.

  3. Put https in front

    The login cookie is marked Secure: a browser never sends it back over plain http. So EventSlide refuses to start without https rather than give you a login form that never logs you in. compose.yaml binds the port to 127.0.0.1 for the proxy to reach and sets TRUST_PROXY_HOPS=1 to match. If your proxy is a container on the same Docker network, delete the ports: block and point it at eventslide:4300.

    With Caddy, the whole proxy is one useful line
    photos.example.com {
      reverse_proxy 127.0.0.1:4300
    }

    In a Caddyfile next to the compose file. Caddy and Traefik pass on what the server needs without being asked. With nginx, add proxy_set_header X-Forwarded-Proto $scheme; and proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;. Without the first, the login cookie is never sent; without the second, all your guests share the proxy’s address in the rate limiter.

  4. Open it and sign in

    Once the proxy is in place, open PUBLIC_URL/login with that email and the generated password (grep BOOTSTRAP_OWNER .env shows it). The first sign-in asks you to choose your own: at least 12 characters, and not a common one. After that, delete both BOOTSTRAP_OWNER lines or keep both: one without the other is refused.

Build the image yourself (a modified copy, an unreleased commit)

From the checkout, instead of pulling the image:

docker compose -f compose.yaml -f compose.build.yaml up --build

Without Docker

You need Node 24 or later, then the npm commands in the “Install” section of the README. Behind your https proxy, TRUST_PROXY_HOPS=1 is required: without it the sign-in form accepts your password and you stay signed out.

Check the image’s signature

The docs/IMAGE-SOURCES.md file says what the image contains, where the source of each part is, and how to check the signature. Nothing is built on your machine: what you run is the published image, the one that is signed.

Backups

Take one before the event and one the morning after. The server stays up while you do. The step people skip is the one that matters: getting the archive off the machine.

# 1. Take it. It prints the name, e.g. /data/backups/eventslide-2026-09-12T08-00-00Z
docker compose exec eventslide node dist/ops/scripts/backup.js

# 2. Take it off the volume, check the copy, and only then delete it there. Until it is
#    off the machine it is on the same disk as the photographs, and the command says so.
A=eventslide-2026-09-12T08-00-00Z
docker compose cp "eventslide:/data/backups/$A" . &&
  docker compose run --rm -v "$PWD/$A:/restore:ro" eventslide \
    node dist/ops/scripts/backup.js --verify /restore &&
  docker compose exec eventslide rm -r "/data/backups/$A"
  • An archive you can trust

    The archive is a folder: a consistent snapshot of the database, every photo, and a manifest of counts and checksums. The command re-reads everything it just wrote before it says OK.

  • It has to leave the machine

    A copy on the same disk as the album does not survive that disk failing. It is a backup once a copy is on another machine, or on a drive you can unplug.

  • Restore with the server stopped

    Always stop the server before restoring: restore replaces the database file, and doing that under a running server leaves a wall serving neither the old evening nor the new one. It verifies the whole archive before touching anything, and refuses to overwrite an installation without --force.

  • Keep your .env too

    The secrets are not in the archive. Restoring photos with new secrets signs every host out.

Details, and what the checks do and do not catch, are in docs/SECURITY.md, section 11. Restoring step by step is in the “Backups” section of the README.

Updates

Run a tagged release, not the tip of the main branch (the one git clone leaves you on). Take a backup first: the migrations a new version applies when it starts only go forward, and a backup is the only way back.

git fetch --tags && git checkout vX.Y.Z
docker compose pull
docker compose up -d

Replace vX.Y.Z with the version you want. What a major version may break, how a break is announced and how to go back are explained in docs/UPGRADING.md.

The AGPL-3.0 licence, in plain words

Here is the short version. It is not legal advice: the text of the licence is what counts.

You can

  • run it, for yourself or for others
  • read it, from end to end
  • change it
  • pass it on to someone else

One extra obligation

If you modify EventSlide and other people use your version over a network, you must offer them the source code of your version, under the same licence. Running an unmodified copy adds nothing.

The link is already there

Every guest and host screen carries a “Source code (AGPL-3.0)” link. You can change where it points (SOURCE_CODE_URL), for a modified version for instance. No setting hides it.

What came before

Version 3.0.0 is the first under AGPL-3.0, “only”: without the “or any later version” clause. Version 2.1.0 is the last under GPL-3.0, and anything published before stays under GPL-3.0 for good.

What the licence asks of someone who runs it, changes it or forks it: docs/LICENSING-FAQ.md.

Source code and contributions

Everything is on github.com/Irony42/EventSlide. Here is where to start. The documents are in English.

Want to help? See CONTRIBUTING.md, or the supporting the project page.

Frequently asked questions

Do I need to be a developer?

No, but you do need to be comfortable with a terminal, Docker and a domain name. If not, the hosted instance exists: request access.

How much does it cost?

The software is free. What remains is the machine, a domain name and a bit of your time.

Can I run it for other people?

Yes. Running an unmodified copy for others adds no obligation. Only a modified version, offered over a network, triggers the source code offer. The detail is in the licensing FAQ.

What if the venue has no network?

On your own machine, the wall keeps playing when the network drops and uploads are queued. However, https needs a real domain name: see the “venue with no domain name” case above. A wall served from a host depends on the venue’s connection.

Would you rather not install anything?

Request access to the hosted instance at app.eventslide.fr: free, by invitation. There is nothing to install.

Request access