Domain Locker: a self-hosted portfolio tracker for domain owners
🌐 The all-in-one tool, for keeping track of your domain name portfolio. Got domain names? Get Domain Locker!
At a glance
- What is it?
- Domain Locker is a TypeScript application that stores your domains in Postgres, fetches registrar, DNS, SSL and host data for each one, and alerts you before expiry. It is aimed at people who own enough domains that a spreadsheet stops working.
- Who is it for?
- Adopt Domain Locker if you hold enough domains that expiry dates and registrar logins no longer fit in your head, and you are willing to run a container plus a Postgres 15 instance to keep the data on your own hardware. Skip it if you have a handful of domains and no interest in maintaining a database, since the managed instance at domain-locker.com exists precisely for that case.
- 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 1 day ago.
- What is it written in?
- Mainly TypeScript, 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 Domain Locker is built around
Domain ownership accumulates in a way that is easy to underestimate. A side project here, a defensive registration there, a client site you inherited, and within a few years the portfolio spans several registrars, each with its own login, renewal date and auto-renew setting. The README frames the goal plainly: complete visibility of your domain name portfolio in one central place, so that you never again lose track of your domains, miss an expiration, or forget which registrar and providers each domain uses. That is the whole pitch. It is not a registrar, it does not buy or transfer domains for you, and it does not sit in the DNS resolution path. It is a record of what you own plus a jobs runner that keeps that record current. The people this suits are domain investors tracking purchase prices and renewal costs, and engineers who administer a set of domains across more than one provider and want a single page that answers where each one is registered and when it lapses.
What gets fetched, and what you have to type in yourself
The README describes the split clearly. For each domain you add, the application analyses it and fetches associated data: SSL certificates, hosts, registrars, IPs, subdomains and DNS records. Everything else is enrichment you supply: tags, notes, purchase price, renewal cost, categories, and links to related resources. The distinction matters when you plan an import. Auto-fetched fields are only as good as the public data behind them, and a registrar record derived from WHOIS or RDAP will reflect whatever the registry exposes, which for privacy-shielded domains can be close to nothing. The cost fields have no automated source at all, so a migration from a spreadsheet is the moment those get populated. The project also states that it keeps a change log of domain updates, which is the feature that turns a one-time inventory into something you can consult after the fact. If a nameserver entry changes without your involvement, the history is where you find out.
How the pieces fit together at runtime
Domain Locker is intended to run in a container. The deployment described in the README has two moving parts: the application image published as lissy93/domain-locker, and a Postgres database, with postgres:15-alpine named as the example. The application binds port 3000 inside the container, mapped to a host port that defaults to 3000. It reaches the database through five environment variables: DL_PG_HOST, DL_PG_PORT, DL_PG_USER, DL_PG_PASSWORD and DL_PG_NAME. A volume mount is mentioned for persistence. That is the entire documented topology, and it is deliberately small: no Redis, no message broker, no separate worker process described. The monitoring and change detection run inside the same application, which keeps the operational surface narrow but also means the fetch jobs share resources with the web interface. On the client side, the README lists a REST or GraphQL API alongside RSS, iCal and Prometheus integrations, which tells you the intended consumption paths beyond the dashboard. What the material does not give is the schema of either API, so treat those integrations as something to inspect in the running instance rather than something you can design against from the README alone.
Self-hosting it: the commands and keys you actually need
The README offers two routes. The managed instance at domain-locker.com is free on the starter plan and requires only a signup with Google, GitHub or email. Self-hosting starts with a one-liner the README prints verbatim: curl -fsSL https://install.domain-locker.com | bash. If you would rather read the configuration before running it, the repository ships a docker-compose.yml, which the README points to as the alternative. The prerequisites are Docker on the host and a Postgres instance. When starting the container, bind 3000 inside the container to your host PORT, which defaults to 3000, then set DL_PG_HOST, DL_PG_PORT, DL_PG_USER, DL_PG_PASSWORD and DL_PG_NAME to match your database. Mount a volume for persistence. Two cautions are worth stating. Piping a remote script into bash is a decision, not a default; the compose file is the auditable path and it is in the repository. And the README's environment section is truncated in the material available here, so the full variable list, including anything controlling notification channels or SSO, is something you should read from the repository before you start the container rather than infer.
Where the design will frustrate you
The dependency on Postgres is a real constraint, not a footnote. It is a sensible choice for a multi-user application with change history and API access, but it means Domain Locker is not a single binary you drop on a VPS and forget. You now own database backups, version upgrades and connection credentials, and the README does not describe a migration path between application versions. That last point is the one to weigh. Releases v0.1.3, v0.1.4 and v0.2.0 landed between February and June 2026, which is a healthy cadence but also a young one, and the material says nothing about whether a schema change ships with upgrade instructions. Second, the notification story is broad on paper: webhook, email, SMS, Slack, Telegram, WhatsApp and more. Breadth of channel list is not the same as reliability of delivery, and the README does not document retry behaviour or what happens when a webhook endpoint is down at the moment an expiry alert fires. If your renewal process depends on that alert arriving, test the channel you chose rather than assuming the list implies a guarantee.
The alternative most people already have, and where it stops
The obvious comparison is a spreadsheet plus registrar emails. That combination is genuinely competitive for a small portfolio: it costs nothing, needs no database, and registrar expiry notices are sent by the party that actually controls the renewal. The difference in approach is where the data lives and who maintains it. A spreadsheet is a document you update manually and it is correct only as of your last edit. Domain Locker is a service that polls and records, so its value comes from the fact that nobody has to remember to update it. The trade is that you now operate a container and a database to get that. There is a middle option the README itself offers: the managed instance, which keeps the fetching and alerting but removes the Postgres from your life at the cost of holding the portfolio data on someone else's infrastructure. Choosing between those three is really a question of how much you trust your own memory versus how much you want to run.
Licence, maintenance and what you are taking on
Domain Locker is MIT licensed, which is permissive: you can run it, modify it and redistribute it, and the licence text is in the repository for the exact terms. This is not legal advice, and if you plan to offer it to others as a service, read the licence and the project's privacy policy yourself. On maintenance, the honest accounting is this: the application is one container, the database is another, and both need attention. Postgres major version upgrades are the recurring chore, and the README's example pins postgres:15-alpine, so that is the version to start from. Application upgrades mean pulling a new image from lissy93/domain-locker and restarting, with the caveat noted earlier that migration behaviour is not documented in the material available. The repository was last pushed in September 2026 and is not archived, so the project is active. Budget for the fact that this is a young codebase with a fast release cadence, and that the person maintaining your instance is you.
Editorial conclusion
Adopt Domain Locker if you hold enough domains that expiry dates and registrar logins no longer fit in your head, and you are willing to run a container plus a Postgres 15 instance to keep the data on your own hardware. Skip it if you have a handful of domains and no interest in maintaining a database, since the managed instance at domain-locker.com exists precisely for that case. Before committing, verify two things yourself: that the notification channel you actually use appears in the alert configuration, and that the REST or GraphQL API returns the fields your existing tooling expects, because the README lists both surfaces without documenting their schemas.
Community notes