LastSignal: A Self-Hosted Dead Man's Switch Where the Server Holds Ciphertext Only
A self-hosted dead man's switch for delivering encrypted messages (E2EE) to your loved ones — when you're gone or unresponsive.
At a glance
- What is it?
- LastSignal is a Ruby on Rails dead man's switch that emails encrypted messages to your contacts when you stop answering check-ins. The design is honest about a real weakness: the KDF salt lives next to recipient public keys, so passphrase strength decides how much a database leak costs you.
- Who is it for?
- Adopt LastSignal if you already run a Linux host, can point DNS at it, and are willing to treat recipient passphrase strength as the load-bearing part of the security model. Do not adopt it if you need a hosted product, a support contract, or a recovery path for a forgotten passphrase, because the repository describes none of those.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 9 days ago.
- What is it written in?
- Mainly Ruby, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The Problem LastSignal Solves, and Who Actually Has It
Most people who want to leave a message for after they die end up writing a letter and hiding it somewhere, or handing a sealed envelope to a lawyer. Both approaches fail the same way: they depend on someone else remembering, and they offer no way to revoke or update the contents. LastSignal replaces the envelope with an email check-in loop. The operator writes encrypted messages, the system emails periodic check-ins, and silence triggers delivery. The README frames the whole thing as email-first, which is a deliberate constraint rather than a missing feature. No app to install for the recipient, no account to create on their side, no push notification infrastructure to maintain. The recipient accepts an invite with a passphrase and reads the message in their inbox when it arrives.
The audience is narrow and specific. You need to be comfortable provisioning a Linux host, running Docker, and pointing DNS records at it. You need a reliable SMTP provider, because the entire delivery mechanism is email. If those three things describe your situation, the project fits. If you want a service where someone else handles uptime and you just log in, the README is explicit that no hosted version exists: the authors state they do not offer any SaaS, paid subscription, or commercial instance, and that anything presented elsewhere as a paid LastSignal product is not official. That warning is unusual to see in a README and it tells you something about how the project expects to be distributed.
How the Check-In Ladder Turns Silence Into Delivery
The mechanism is a state machine driven by scheduled jobs. Defaults are 30 days between check-ins, 3 reminder attempts including the first, 7 days between attempts, and a 15-day trusted contact pause. The README walks through a concrete timeline. Last check-in on April 1 leaves the account active. Reminder one on May 1 is still active. Reminder two on May 8 puts the account in a grace state. Reminder three on May 15 is the final reminder and also pings the trusted contact, moving the account to cooldown. Delivery follows on May 22 if nobody responds.
The trusted contact is a pause button, not an override. If that person confirms on May 16, delivery is pushed to May 31, and a new ping goes out that day. If the user checks in or the contact confirms again, delivery is pushed further. Otherwise the message goes out on June 7. That is a meaningful design choice: the trusted contact can buy time but cannot cancel the switch permanently, and the README does not describe a way for them to do so. The per-recipient delay setting adds another layer. You can set a number of days that delays when a recipient can decrypt after delivery, which the README suggests for staggered access or time-sensitive information. Note that this delays decryption, not delivery; the message reaches the inbox and sits there until the delay elapses.
All timing values are configurable per user in Account Settings, so the defaults are a starting point rather than a fixed policy. One detail worth flagging: check-ins are skipped unless at least one message is linked to an accepted recipient. An account with no accepted recipients will not generate check-in emails at all, which is sensible for a fresh install but can confuse someone testing the flow before a recipient has accepted.
The Crypto Stack and the Salt Trade-Off the README Admits
LastSignal uses Argon2id with a 256MB memory parameter, XChaCha20-Poly1305 for authenticated encryption, and X25519 for key exchange, all via libsodium. The server never sees plaintext, and the README describes the architecture as zero-knowledge, meaning the operator cannot read stored messages either. That claim only holds if the key material never reaches the server in a usable form.
Here is where the project is more candid than most. LastSignal uses a server-generated KDF salt stored alongside recipient public keys. The README calls this a deliberate architectural trade-off and explains what it buys: deterministic key regeneration from a passphrase. The cost is stated plainly. If an attacker obtains the database through server compromise, a data breach, a malicious operator, or a law enforcement request, they get the salt and can run offline brute-force attacks against recipient passphrases with no rate limiting. The README marks strong passphrases as critical, and it is right to. A weak passphrase plus a database leak equals a readable message, and the zero-knowledge claim does not survive that combination.
This is the single most important thing to understand before deploying. The threat model is not "the server is untrusted, therefore I am safe." It is "the server is untrusted, and my safety depends on how expensive it is to guess the passphrase that unlocks the salt." Argon2id at 256MB raises that cost substantially, but it does not eliminate it. Anyone evaluating LastSignal should read the full security page at lastsignal.app/security rather than relying on the README summary, because the README explicitly defers to that page for the complete picture.
Getting It Running: Dev Stack, Docker, and the Demo Commands
Local development needs Ruby 3.4 or later, SQLite 3 with the sqlite3 gem at 2.1 or above, and Node.js for Tailwind. The README gives a fresh Ubuntu install as apt-get update followed by apt-get install for git, ruby, bundler, and libyaml-dev. From there the sequence is git clone, cd lastsignal, bundle install, cp .env.example .env, bin/setup, bin/dev, then open http://localhost:3000 and request a magic link. Emails open in the browser through letter_opener, so you never need a real SMTP provider during development.
If you would rather not install Ruby locally, the Docker path is one command: docker compose -f docker-compose.dev.yaml up --build. That brings up the app on port 3000 and a Mailhog inbox on port 8025, which is a cleaner way to inspect the message sequence than letter_opener because you can see the whole mailbox at once.
The demo helpers are the part worth knowing about, because waiting 30 days to test a dead man's switch is not practical. After logging in, adding a recipient, accepting the invite with a passphrase, and creating a message, you can drive the state machine manually. bin/rails demo:checkins:status EMAIL=you@example.com shows where the account sits. bin/rails demo:checkins:advance EMAIL=you@example.com sends the next email in the sequence. bin/rails demo:checkins:advance_days EMAIL=you@example.com DAYS=7 simulates time passing and runs the check-in job. bin/rails demo:checkins:deliver EMAIL=you@example.com skips straight to delivery. Under Docker, prefix each with docker compose -f docker-compose.dev.yaml exec app. The README notes these helpers only run in development and test environments, so they are not a production backdoor. Tests run through bin/test, with targeted specs available for individual files such as spec/jobs/process_checkins_job_spec.rb.
Production Deployment Is Kamal, Docker, and an SMTP Provider
The README describes production deployment through Kamal and states you need only Docker, SSH access, and a reliable SMTP provider. The server preparation is a Linux host (Ubuntu 22.04 or later is recommended), Docker installed, ports 80 and 443 open, and DNS A or AAAA records pointed at the server IP. Configuration starts with cp .env.production.example .env.production, and the README lists the required values: KAMAL_* settings covering image, registry, server, and domain; APP_BASE_URL and APP_HOST; SMTP_* credentials; and an optional ALLOWED_EMAILS allowlist. The README text cuts off mid-sentence at that last item, so the exact semantics of the allowlist are not fully documented in the material available.
There are no releases retrieved for this repository, which means there is no versioned upgrade path to point at. That matters for maintenance cost. LastSignal is a Rails 8 application on Ruby 3.4 with SQLite as the database, and it tracks whatever the master branch contains. Upgrading means pulling the repository, rebuilding the image, and redeploying through Kamal. There is no changelog in the supplied material, so you cannot tell what changed between two points in time without reading commits yourself. For a personal deployment that is tolerable. For anything with multiple operators or a change-control process, it is a gap.
The licence is MIT, which permits commercial use, modification, and redistribution with the copyright notice and permission notice preserved. That is a permissive licence, and nothing in the README adds restrictions on top of it. The README does state that the authors offer no hosted service, which is a statement about their intentions rather than a licence term. If you fork LastSignal and run it as a paid service, the MIT licence does not appear to stop you, though the README's warning suggests the authors would object. That is a question for a lawyer, not for this article.
The Optional Keep-Alive Webhook and What It Changes
Beyond the email loop, LastSignal supports an external keep-alive token that lets a machine send a check-in to /webhooks/keepalive. The README describes this as an add-on for automations and explicitly says it is not a replacement for the default email-first model. The use case is clear enough: if you have a cron job or a monitoring system that already knows whether a host is alive, you can wire it to the endpoint and let the machine prove liveness instead of relying on yourself to click a link.
The risk is equally clear, and the README does not spell it out. A keep-alive endpoint is a second authentication path, and if the token leaks or the automation keeps firing after you stop caring about the account, the switch never trips. A misconfigured cron job that pings the webhook forever is functionally identical to a user who never dies, from the system's perspective. The README does not describe token rotation, scoping, or revocation for this endpoint in the material available, so treat it as a feature for people who understand exactly what their automation does and can guarantee it stops when it should. For everyone else, the email check-in is the safer default and the one the project is built around.
Where LastSignal Is the Wrong Tool, and What to Use Instead
The clearest failure mode is the forgotten passphrase. Recipients accept an invite with a passphrase, and the encryption depends on that passphrase plus the server-side salt. If a recipient loses it, the README describes no recovery mechanism. There is no escrow, no reset link, and no operator override, because an override would break the zero-knowledge property. A dead man's switch that delivers an unreadable message has failed at the only job it had.
The second failure mode is SMTP. Every check-in, reminder, trusted contact ping, and final delivery goes through email. If your provider rate-limits, marks the mail as spam, or goes down during the delivery window, the sequence stalls. Self-hosting removes the dependency on a vendor's application but not on a vendor's mail relay. Budget for a provider you trust and test deliverability before you rely on it.
For a different approach, consider a plain encrypted archive plus a lawyer or a safe deposit box. That is not software, and it is the honest comparison: a sealed envelope with instructions has no salt to leak, no SMTP dependency, and no passphrase for a recipient to forget, because you can hand over the key in person. It also has no automatic triggering, no revocation, and no way to update the contents without physically replacing the envelope. LastSignal wins on updateability and on not requiring a human to remember anything at the moment it matters. The envelope wins on simplicity and on not introducing a database that, if leaked, becomes an offline cracking target. If your messages are short, few, and unlikely to change, the envelope is genuinely competitive. If they are long, likely to be revised, or you want staggered access through the per-recipient delay, LastSignal is doing something the envelope cannot.
Editorial conclusion
Adopt LastSignal if you already run a Linux host, can point DNS at it, and are willing to treat recipient passphrase strength as the load-bearing part of the security model. Do not adopt it if you need a hosted product, a support contract, or a recovery path for a forgotten passphrase, because the repository describes none of those. Before trusting it with real messages, read the full security page at lastsignal.app/security, run the Docker compose stack, and walk one message through bin/rails demo:checkins:advance until it lands in Mailhog.
Community notes