Open-source project
allo-/ffprofile avatar
allo-/ffprofile

Firefox Profilemaker explains every default it writes into your profile

A tool to create firefox profiles with personalized defaults.

844 stars59 forksHTMLAGPL-3.0

At a glance

What is it?
ffprofile is a small Django application that generates a Firefox profile with privacy oriented defaults, where each option carries a short description instead of appearing as a line in an opaque user.js. It runs as a web form, ships a Docker image, and deliberately leaves out settings it thinks users should not have to read.
Who is it for?
ffprofile suits someone who wants a privacy tuned Firefox without reverse engineering a hundred lines of user.js, since the wizard explains each choice and the same code can run locally or through Docker. It is the wrong tool for a user who wants performance tuning, a large extension list or a custom interface, because the project deliberately omits all three, and it does not manage profiles for you after the fact.
Can I use it commercially?
Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
Is it still maintained?
Yes. The repository last received commits 10 days ago.
What is it written in?
Mainly HTML, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem with importing a stranger's user.js

The usual way to configure a Firefox profile for privacy is to download a user.js file from somewhere and drop it into the profile directory. The problem is not that the settings are wrong, it is that you have no idea what any of them do.

ffprofile is a web application for creating Firefox profiles with preconfigured defaults, and its stated focus is privacy and removing unnecessary features. It disables intrusive features such as telemetry, allows web features that could be used to fingerprint the browser to be switched off, and adds options for controversial features such as Pocket.

The design goal is stated explicitly: instead of importing a long user.js without knowing what the options do, every option has a short description, so the user can understand why they would want to enable or disable it and what the side effects are. There is no one size fits all, so the tool is a wizard that produces a personalised profile rather than a single opinionated configuration.

The project and the website that runs this code are explicitly not affiliated with or endorsed by Mozilla. The instance at ffprofile.com is available if you only want a profile, and the repository exists so you can run your own copy, either to add your own settings or to avoid trusting the hosted site at all.

A Django form that writes a profile

The implementation is a plain Django application, and the repository layout shows the whole thing: forms.py holds the wizard, views.py the request handling, models.py the data layer, urls.py the routes, and a templates and static directory for the rendered pages. There is a profiles directory for the secondary profile presets, an admin.py, a migrations directory and a tests.py.

The project does not use database features, which the README is careful to explain, but it does need the session framework, and depending on the configuration that session framework uses a database backend. SQLite is enough for that.

Two scripts at the root are worth knowing about. get_addons.sh is the helper for fetching the extensions, and addon_urls.txt holds the list of extension URLs the project uses, with the matching addons.mozilla.org pages next to each one. merge.py sits alongside them.

The interesting design choice is that the extension list is stored as files on disk rather than being downloaded at request time. You provide the XPI files yourself, and the application bundles them into the profile it generates.

Extension file names have to match the manifest

The one fiddly part of running this yourself is the extensions folder, and the README states the rule clearly: the Firefox addons that will be included in profiles must be provided as XPI files in an extensions folder at the path from where you run the project, and they need to be named exactly as they are in their install.rdf or manifest.json file, because otherwise Firefox will not install them.

That is not a stylistic request. Firefox identifies an add-on by the id in its manifest, so a file called [email protected] is recognised and a file called ublock.xpi is not.

The addon_urls.txt file lists the current URLs and names, and the set is the familiar privacy stack: CanvasBlocker, the Google No Tracking URL redirect addon, HTTPS Everywhere, uBlock Origin, uMatrix, Privacy Badger, Cookie AutoDelete, Decentraleyes, ClearURLs, Temporary Containers and Multi-Account Containers, the last two under their jetpack style names.

If you add an extension of your own, the process is to fetch the XPI, drop it into the extensions folder, and name it after the id in its manifest. The make target for the containerised path bind mounts the extensions directory into the container for exactly this reason, so the folder on the host is the folder the application reads.

Installing locally with make, or in a container

The Makefile drives the local setup, and the install target creates the virtual environment, installs the dependencies, copies the environment template and generates the Django project. The steps it performs are visible in the target:

bash
install: remove
	@echo Create python virtual environment
	python3 -m venv venv
	. venv/bin/activate
	@echo Install dependencies
	pip install -r requirements.txt
	cp .env.example .env
	make -s create-project

The create-project target then runs django-admin startproject, symlinks the application directory into the new project, appends the INSTALLED_APPS and settings lines to settings.py, wires the URLs into urls.py, and runs the migrations. The remove target erases the venv and project directories and the .env file, which is why install depends on it and why a fresh install always starts from a clean state.

Only one runtime dependency is declared, and it is pinned to a narrow range:

text
Django>=5.0.1,<5.1.0

The container image builds in two stages on python:3.11.7-alpine3.19, installing the dependencies into the user directory in the first stage and copying them into the runtime image, then running make create-project, and it serves the application on port 8000:

dockerfile
CMD [ "./project/manage.py", "runserver", "0.0.0.0:8000"]

The environment file is a template with a random secret key placeholder, DEBUG turned on, and the allowed hosts and CSRF trusted origins set to wildcards. The comment suggests generating a key with base64 over /dev/urandom. Those defaults are fine for a local run and wrong for anything exposed, so the first edit to make is the secret key.

What the project deliberately leaves out

The exclusions are the most instructive part of the README, because they explain what kind of tool this is.

Many useful add-ons are not included. The stated reason is that the author keeps the list short because add-ons can slow down the browser, they may be insecure, and there are simply too many good ones to include. Performance settings and similar optimisations are left out too, on the grounds that they are often a trade-off and not easy to understand, with the argument that power users can change them themselves and get them from one of the many user.js files other people provide, while the average user is probably better off with the defaults.

Larger interface changes are excluded because they are personal choices. And options that are already easy to configure are left alone, with the reasoning that if Firefox already asks for permission before doing something the first time, a preconfigured answer is probably unnecessary.

The stated principle is that keeping it simple enough implies it cannot contain everything, because if there are too many options people will not have the time to read every description and weigh the costs and benefits. That is a defensible editorial position, and it is also a limitation: a user who wants a specific configuration has to fork it or edit the output by hand.

Secondary profiles exist and are not finished

The project has basic support for profiles, and it is planned to add a function to choose multiple profiles, with names such as security, privacy and classic ui, or similar combinations. Once that is implemented, settings that do not belong in the main profile can be included in secondary profiles.

Until then, the bug tracker is where the work is visible. The README points out that it contains infrastructure issues for these things and issues tagged as other profile? which may be implemented at some point.

That is a fair summary of the state of the feature. The concept of a per profile settings set is not finished, and anyone planning to deploy this should treat the profiles directory as a starting point rather than a working system.

The fork path is also open. The project is provided as open source partly so that people can add options in their own fork, and the author says he may then pick up some of the options that contributors implement at a later point in time. That is a reasonable arrangement for a small project and it means the extension list and the option set are effectively community owned.

Licence, releases and where the project stands

The licence is AGPL-3.0, which is a deliberate choice for a web application. The AGPL was written so that modifications made available over a network are also subject to the licence, and for a hosted profile generator that is the part that matters. Anyone who forks this and runs it as a service has to publish their changes. Any specific question about how that applies to your use belongs with your own counsel.

The repository has no GitHub releases, so there is no version history to point at and no changelog to read on the releases page. The last push was on 2026-10-13, and the repository is not archived, so work is still landing on the master branch.

The dependency story is worth a note. The requirements file pins Django to the 5.0 series, while the container image and the development environment are built on Python 3.11. That combination works, but it means the application tracks one Django minor version, so an upgrade involves a deliberate bump of the pin rather than a pull of the latest release.

The hosted service at ffprofile.com is the fastest route to a profile, and running your own instance is the route to a profile you fully control. The repository, the Dockerfile and the INSTALL.md file are what you need for the second one.

Editorial conclusion

ffprofile suits someone who wants a privacy tuned Firefox without reverse engineering a hundred lines of user.js, since the wizard explains each choice and the same code can run locally or through Docker. It is the wrong tool for a user who wants performance tuning, a large extension list or a custom interface, because the project deliberately omits all three, and it does not manage profiles for you after the fact. Before deploying it, put the extension XPI files in the extensions folder with the exact names from their manifest files, set a real SECRET_KEY instead of the placeholder, and read the list of what the project leaves out to decide whether the defaults match your own view of privacy.

Frequently asked questions

How do I add extensions to the profiles that ffprofile generates?

You provide the XPI files yourself in an extensions folder at the path from where you run the project, and each file must be named after the id in its install.rdf or manifest.json, because Firefox will not install them otherwise. The README lists the current addon URLs and names in addon_urls.txt.

Does ffprofile need a database?

The project does not use database features, but it requires the Django session framework, which depending on the configuration uses a database backend. Using the simple SQLite database is sufficient for that.

Can I run my own instance of the Firefox profile maker?

Yes, and that is the point of the repository. The Makefile install target creates a virtual environment, installs the dependencies, copies .env.example to .env and generates the Django project, and a Dockerfile is included for running the same application in a container on port 8000.

Official sources

  1. allo-/ffprofile on GitHub
  2. Issues
  3. License: AGPL-3.0
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/allo-ffprofile.svg)](https://hysenlabs.com/projects/allo-ffprofile)

Was this useful?