# luolongfei/freenom: automatic renewal for Freenom domains with Docker

> A PHP 8.1+ script that logs into Freenom accounts and renews free domains on a schedule, shipped as a Docker Compose stack with a separate AWS WAF solver container. Useful if you still hold Freenom domains, and only if you do.

**luolongfei/freenom** — Freenom 域名自动续期。Freenom domain name renews automatically.

- Repository: https://github.com/luolongfei/freenom
- Stars: 3,337 · Forks: 1,561
- Language: PHP
- License: MIT
- Published: 2026-09-24 · Updated: 2026-09-24 · Language: en
- Canonical page: https://hysenlabs.com/en/projects/luolongfei-freenom

## The problem: Freenom renews one year at a time, by hand

Freenom hands out free top-level domains, and the README states the author's reason for writing this: those domains have to be renewed every year, one year at a time. Register a handful on different dates and you end up with a rolling calendar of manual renewals, each one a fresh login to the Freenom site. Miss one and the domain lapses.

luolongfei/freenom exists to remove that login. It is aimed at people who already hold Freenom domains and want the renewal step to happen on a schedule without them watching a calendar. It is not a domain registrar, not a DNS manager, and not a general certificate or hosting tool. The scope is narrow on purpose: authenticate, renew, report. If you do not have a Freenom account, there is nothing here for you.

## How the renewal loop works, and why there are two containers

The repository is a PHP application (PHP 8.1 or newer according to the README badge, and the Dockerfile builds on php:8.5.3-cli-alpine3.23). Credentials and notification settings live in a .env file, with FREENOM_USERNAME and FREENOM_PASSWORD for a single account and MULTIPLE_ACCOUNTS for several in the form '<account1>@<password1>|<account2>@<password2>'. The .env.example notes that single and multiple account settings are merged and de-duplicated when read.

The interesting part is the second container. The docker-compose.yml defines a freenom service and an aws-waf-solver service, with freenom declaring depends_on: aws-waf-solver. The solver image is luolongfei/aws-waf-solver, given shm_size: 2gb, privileged: true and pull_policy: always. Both services share the same ./.env mounted at /app/.env and both extend common.yml. The naming points at the AWS WAF challenge that Freenom sits behind: the solver container handles the browser-side challenge, and the PHP container does the login and renewal. That is an inference from the compose file and image name; the README excerpt does not spell out the handshake between them.

Notifications are a first-class part of the loop. The README says a notification goes out whether renewal succeeds, fails, or crashes, and that renewal messages include how many days remain before an unrenewed domain expires. Channels are Email, Telegram Bot, WeCom, ServerChan, Bark and Pushplus. The author's own recommendation in the README is to skip ServerChan because of its daily message cap and paid tier, and to prefer WeCom or Bark instead. That is an opinionated call worth taking seriously, since a renewal notifier that silently hits a quota limit defeats the purpose.

## Installing it with Docker Compose and running the first renewal

The README lists Docker deployment as recommended and usually the simplest option. Docker Compose is the path shown in the repository. Start by creating your .env from the example file, then fill in the Freenom credentials. Note the quoting rules from .env.example: a '#' inside a password must be wrapped in single quotes or parsing stops at that character. The README does not give a literal copy command, and the .env.example itself is the template.

Open .env and set the account block. The variable names and the shape of MULTIPLE_ACCOUNTS come straight from .env.example, including the angle brackets.

```bash
FREENOM_USERNAME=''
FREENOM_PASSWORD=''
MULTIPLE_ACCOUNTS=''
MAIL_ENABLE=0
```

If you want email notifications, the README says to set MAIL_USERNAME and MAIL_PASSWORD to the sending mailbox and its password or token, set TO to the recipient, and set MAIL_ENABLE=1. Gmail means an app password, not a less secure app login; QQ Mail and 163 Mail mean an authorization code. Set MAIL_ENABLE=0 to turn email off entirely.

The Makefile wraps the common operations. The up target pulls the latest code, pulls the solver image, then builds and starts the stack detached. The n variable defaults to 20 and controls the log tail.

```bash
make up
make logs n=50
```

After make up you should see two containers, freenom and aws-waf-solver, and the logs target streams from both. The Makefile's up target also runs docker system prune -af, which removes unused images and build cache on your host. That is convenient on a throwaway VPS and less convenient on a machine running other containers, so read the target before you type it. The Dockerfile's CMD is crond -f, so the container runs the scheduler in the foreground and renewals happen on its internal cron rather than once at startup.

## The privileged containers and the solver dependency are the real costs

Two things stand out in docker-compose.yml. Both services are privileged: true, and aws-waf-solver is given shm_size: 2gb. A privileged container has broad access to the host, so this stack is not something to drop onto a shared machine alongside unrelated workloads. The Dockerfile even carries a comment noting that some environments do not support the VOLUME keyword, which is why it does not declare data volumes.

The second cost is the coupling. The freenom service depends_on the aws-waf-solver image, and that image is pulled with pull_policy: always. If the solver image cannot be pulled, or if its challenge-solving approach stops matching whatever Freenom currently serves, renewal breaks even though the PHP side is untouched. The README excerpt does not document a fallback path for that case, and it does not describe how to run the renewal without the solver. Treat the solver as a hard dependency until you find evidence otherwise in the source.

The third limitation is conceptual. This tool automates a login to a third-party service on your behalf. If Freenom changes its login flow, adds a new challenge, or restricts the accounts involved, the script has no way to negotiate with it. The README's own framing is a personal script that grew a community, and the deployment list shows that drift: Mogenius is marked no longer viable, and Cloud Function deployment is marked no longer actively supported. Hosted platforms come and go around a project like this faster than the core logic changes.

## Compared with a plain cron job and a curl script

The obvious alternative is a shell script on cron that posts to Freenom's renewal endpoint with a stored cookie. That approach is smaller and has no privileged containers, and for a single account it may be all you need. The difference is everything around the request. This project carries a notification layer with six channels, expiry-day reporting in the message body, multi-account parsing with de-duplication, and a dedicated solver container for the WAF challenge. A hand-rolled curl script gives you none of that, and you would be writing the challenge handling yourself.

The other alternative is to stop renewing and move the domain. That is a decision about Freenom, not about this tool, and it is outside what the repository can answer. What the repository does tell you is that the author still maintains the renewal path: v0.7.0 landed on 2026-03-20 with the note that all dependencies were updated to the latest version. The prior release, v0.6.2, was on 2024-02-25, so the project went roughly two years between releases before that dependency refresh. The last push to the repository was on 2026-08-01.

## Licence and the cost of keeping it running

The project is MIT licensed, with the LICENSE file at the repository root. MIT is permissive: you can use, modify and redistribute it, including commercially, provided the copyright notice and permission notice travel with it. This is a summary of what the identifier normally means, not legal advice; read LICENSE and your own obligations if the distinction matters to you.

Upgrade cost is mostly the Docker images. The Makefile's up target does a hard reset to the remote branch (git fetch --all, git reset --hard, git pull) before rebuilding, so running make up on a machine with local edits to tracked files will discard them. The solver image is always re-pulled. The PHP image is pinned in the Dockerfile to php:8.5.3-cli-alpine3.23, so the language runtime only moves when that line changes. Given the two-year gap between v0.6.2 and v0.7.0, expect dependency refreshes to arrive in bursts rather than continuously, and read CHANGELOG.md before pulling, since a dependency bump in a scraper-style tool can change behaviour at the edges.

## Conclusion

Adopt it if you still hold Freenom domains and want renewal plus a notification on every run, and you are comfortable running two privileged containers. Skip it if you have no Freenom account, because the whole program is a login-and-renew loop against one provider. Before trusting it, confirm the Freenom accounts in your .env still authenticate, check that the aws-waf-solver image pulls on your host (it needs shm_size 2gb and privileged), and read CHANGELOG.md for what v0.7.0 changed in the dependencies.

## FAQ

### How do I use luolongfei/freenom to renew my domains?

Create a .env from .env.example, fill in FREENOM_USERNAME and FREENOM_PASSWORD (or MULTIPLE_ACCOUNTS for several accounts), choose a notification channel, then run make up to build and start the two containers. The freenom container runs crond in the foreground and renews on its internal schedule.

### Does luolongfei/freenom need Docker?

No. The README lists Docker deployment as recommended and usually simplest, but it also documents deploying from source, which requires PHP 8.1 or newer. Docker Compose is the path shown by the repository files, including the Makefile targets.

### What notification channels does luolongfei/freenom support?

Email, Telegram Bot, WeCom, ServerChan, Bark and Pushplus. The README says to configure only the one you pick, and the author recommends against ServerChan because of its daily message cap and paid tier.

### Why does luolongfei/freenom run a second container called aws-waf-solver?

The docker-compose.yml defines aws-waf-solver as a separate service that the freenom container depends on, using the image luolongfei/aws-waf-solver with shm_size 2gb and privileged: true. The name indicates it handles the AWS WAF challenge in front of Freenom, though the README excerpt does not document the handshake between the two containers.

### Can luolongfei/freenom manage multiple Freenom accounts?

Yes. Set MULTIPLE_ACCOUNTS in the form '<account1>@<password1>|<account2>@<password2>|<account3>@<password3>' without spaces and without omitting the angle brackets. The .env.example states that single-account and multi-account settings are merged and de-duplicated when read.

## Sources

- [Issues](https://github.com/luolongfei/freenom/issues)
- [License: MIT](https://github.com/luolongfei/freenom/blob/main/LICENSE)
- [luolongfei/freenom on GitHub](https://github.com/luolongfei/freenom)
- [README](https://github.com/luolongfei/freenom/blob/main/README.md)
- [Releases](https://github.com/luolongfei/freenom/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/en/projects/luolongfei-freenom
