If you’re like me (and even if you’re not) having all of your Firefox instances (including LibreWolf with some additional configuration) synchronized is quite the produtivity boost. It’s really nice (or will be) when I setup / try a new OS. This includes Firefox Mobile and sending tabs to your phone. It’s very nice. But I’m a self-hoster and that’s always my default if possible so that’s what I did.
This is a complex endeavor. It doesn’t need to be but I think the lack of people doing it and the lack of good documentation contributes to that complexity. Luckily for all of us jackyzy823* has done a lot of the heavy lifting for us here. So I started with that and did as instructed here. But then I took that and made it work for me which meant adapting it for Traefik instead of nginx. I also typically have two networks defined in my setups: traefik and backend. The traefik network is just that; it’s for the the reverse proxy. The backend network then isn’t used for the reverse proxy and is just for internal services to communicate with each other internally.
This mainly involved creating the labels and applying them appropriately. I’ll document the services and their labels here and then I’ll work on a PR for the Github repo that jackyzy823 has and see if we can get it added to the examples. The first to look at is syncserver. It’s straightforward just taking care to make sure that we specify the network for traefik to use and the port we want traefik to route requests to, in this case 5000. Notice that we use the token subdomain. That’s the convention that’s used even though it’s the syncserver.
syncserver:
labels:
- traefik.enable=true
- traefik.http.routers.syncserver.rule=Host(`token.example.com`)
- traefik.http.routers.syncserver.tls=true
- traefik.docker.network=traefik
- traefik.http.services.syncserver.loadbalancer.server.port=5000
- traefik.http.routers.syncserver.service=syncserver
The next to look at is the auth server. The important thins here are the same for syncserver with the added difference that we need it to resolve to two different subdomains (for this setup).
fxa-auth-server:
labels:
- traefik.enable=true
- "traefik.http.routers.fxa-api.rule=Host(`api.example.com`) || Host(`oauth.example.com`)"
- traefik.http.routers.fxa-api.tls=true
- traefik.docker.network=traefik
- traefik.http.services.fxa-api.loadbalancer.server.port=9000
- traefik.http.routers.fxa-api.service=fxa-api
The next one is the profile server. It follows the same pattern and only resolves to one subdomain like the syncserver.
fxa-profile-server:
labels:
- traefik.enable=true
- traefik.http.routers.profile.rule=Host(`profile.example.com`)
- traefik.http.routers.profile.tls=true
- traefik.docker.network=traefik
- traefik.http.services.profile.loadbalancer.server.port=1112
- traefik.http.routers.profile.service=profile
And the content server….
fxa-content-server:
labels:
- traefik.enable=true
- traefik.http.routers.content.rule=Host(`www-fxa.example.com`)
- traefik.http.routers.content.tls=true
- traefik.docker.network=traefik
- traefik.http.services.content.loadbalancer.server.port=3030
- traefik.http.routers.content.service=content
And the graphql server…
fxa-graphql-api:
labels:
- traefik.enable=true
- traefik.http.routers.graphql.rule=Host(`graphql.example.com`)
- traefik.http.routers.graphql.tls=true
- traefik.docker.network=traefik
- traefik.http.services.graphql.loadbalancer.server.port=8290
- traefik.http.routers.graphql.service=graphql
And the channel server…
channelserver:
labels:
- traefik.enable=true
- traefik.http.routers.cs.rule=Host(`channelserver.example.com`)
- traefik.http.routers.cs.tls=true
- traefik.docker.network=traefik
- traefik.http.services.cs.loadbalancer.server.port=8000
- traefik.http.routers.cs.service=cs
I currently have all of my desktop instances of Firefox and Firefox on Android syncing so I think everything is working properly. One change I would like to make soon is switching to the Rust based syncserver implementation.
I think there’s also an issue with some static content that needs to be served during the web based auth/login process that I need to deal with but does not affect the functionality. Also signing a device in using the QR code generated does not work because it points to the Mozilla servers regardless of what you have configured.
I would also like to update to the latest mozilla/fxa-mono image and then start down the path of reimplementing everything in Rust. ;)