This is the official server for FMD Android written in Go.
The FMD app can register an account on FMD Server. The app can then upload its location at regular intervals. You can also push commands to the FMD app on your device from FMD Server, e.g. to make your device ring.
At its core, FMD is just a binary that you can run directly. If you are experienced and have settled on your own way to deploy applications, feel free to stick to that.
go run main.go serve
# or
go build
./fmd-server serveAlternatively, or if you are new to hosting applications, we recommend to run FMD Server with Docker.
Quickly try FMD Server on your laptop from the command line:
docker run --rm -p 8080:8080 registry.gitlab.com/fmd-foss/fmd-server:v0.11.0You can now visit FMD Server's web interface in your browser at http://localhost:8080.
You can register you FMD app using the server URL http://<your-laptops-ip>:8080.
Note that these steps are only for quick on-laptop testing and NOT for production!
FMD Server uses the following paths:
| Default location | Recommended location | |
|---|---|---|
| Config file | ./config.yml |
/etc/fmd-server/config.yml |
| Directory with the SQLite database | ./db/ |
/var/lib/fmd-server/db/ |
| Directory with web static files | "" (embedded) |
/usr/share/fmd-server/web/ |
These can be configured via CLI flags. The directories can also be configured in the config file.
The default location is the current working directory, because it is expected to be writable by the current user.
When installing FMD Server as an admin, use the recommended locations for a more Unix-like setup. However, this requires root privileges to create and chown the required locations (hence it is not the default).
The Dockerfile uses the recommended locations, so mount your volumes there (as shown below).
When /etc/fmd-server/config.yml is present and used, FMD Server also reads in /etc/fmd-server/local.yml.
This is similar to how fail2ban uses jail.conf and jail.local: it allows packagers to use config.yml and allows admins put their settings in local.yml. Thus admins don't have to edit the packager's config.yml (which would cause conflicts if a package update changes the config.yml).
Values in local.yml override their counterpart in config.yml.
⚠️ FMD Server is still pre-1.0. Therefore, minor versions can introduce breaking changes. It is recommended to pin a version and read the changelog before upgrading.
The following is an (incomplete) example docker-compose.yml for deploying FMD Server with Docker Compose.
services:
fmd:
# Use the prebuilt image
image: registry.gitlab.com/fmd-foss/fmd-server:v0.11.0
# Or build the image yourself
# build: https://gitlab.com/fmd-foss/fmd-server.git#v0.11.0
container_name: fmd
ports:
- 127.0.0.1:8080:8080
volumes:
- './fmddata/db/:/var/lib/fmd-server/db/'
restart: unless-stoppedReplace the version with the latest release.
Persisting storage:
FMD has a database and needs to persist it across container restarts.
You need to mount a Docker volume to the directory /var/lib/fmd-server/db/ (inside the container).
It must be readable and writable by uid 1000 (ideally it is owned by uid 1000).
Networking: FMD Server listens for HTTP connections on port 8080. This example has a port mapping from "127.0.0.1:8080" (on the host) to port 8080 (inside the container). You need to set up your own reverse proxy. The reverse proxy should terminate TLS and forward connections to the FMD container. Instead of the port binding you can also use Docker networks (e.g. to connect your proxy container to the FMD container).
Run with docker compose up --build --detach.
It is recommended to harden your Docker containers as decribed by OWASP. This means:
- Run a read-only container.
- The only path that FMD Server writes to is the database directory, which should be mounted as a volume.
- Drop all capabilities.
- Disallow acquiring new privileges.
On the Docker CLI, pass:
docker run --read-only --cap-drop=all --security-opt=no-new-privileges # ... rest of commandIn Docker Compose, set:
services:
fmd:
# other lines omitted
read_only: true
cap_drop: [ALL]
security_opt: [no-new-privileges]Use the following Caddyfile:
fmd.example.com {
reverse_proxy localhost:8080
}
Caddy will automatically obtain a certificate from Let's Encrypt for you.
See the example nginx config.
When uploading pictures you might see HTTP 413 errors in your proxy logs ("Content Too Large"). To fix this increase the maximum body size, e.g to 20 MB:
client_max_body_size 20m;
The FMD Server binary (whether run in Docker or not) assumes that request paths start at the root ("/").
That is, it assumes that you host FMD Server on a (sub-)domain, e.g., https://fmd.example.com.
If you host FMD Server in a subdirectory, e.g., https://example.com/fmd/, you need to configure
your proxy to strip the subdirectory before forwarding the request to the backend.
FMD Server does not know how to resolve /fmd/api/, it only knows about /api/.
⚠️ This setup is not recommended and provided for your convenience only.
If you don't want to use a reverse proxy, FMD Server can terminate TLS for you. However, you need to manage (and regularly renew!) the certificates.
- Get a TLS certificate for your domain.
- Set the
ServerCrtandServerKeyin the config file (see below). - Mount the certificate and the private key into the container:
# other lines omitted
volumes:
- ./server.crt:/etc/fmd-server/server.crt:ro
- ./server.key:/etc/fmd-server/server.key:roThe config.example.yml contains the available options to configure FMD Server.
Copy this file to config.yml and edit it to your liking.
By default, FMD Server will look for the config.yml at /etc/fmd-server/config.yml
and in the current working directory.
You can pass a custom location with --config.
With Docker you can mount it with -v ./config.yml:/etc/fmd-server/config.yml:ro (for CLI)
or for Compose:
# other lines omitted
volumes:
- ./config.yml:/etc/fmd-server/config.yml:roNOTE: yml not yaml!
All values that can be set in the config file can also be set via environment variables.
Simply set FMD_CONFIGFIELDNAME, e.g. FMD_PORTINSECURE.
services:
fmd:
environment:
FMD_PORTINSECURE: 8888
# other lines omittedSome values can also be set via CLI flags.
See fmd-server serve --help for details.
FMD Server uses Viper, which has the following precedence rules (from highest to lowest):
CLI flag > env var > config file value > default value
The static files for the website are included in the Go binary using go:embed.
This is the recommended way to use FMD Server.
If you want to manually provide the web/ directory (for example, for custom styling), you can provide a custom path with the --web-dir option.
This disables the embedded static files and instead reads all static files from the provided path.
- AUR package, maintained by @Chris__
The community has developed the following alternative servers:
The community has developed the following alternative clients:
These implementations are unofficial, and are not audited by the FMD authors. Links are provided for your convenience only. Use at your own risk.
Logs are written to stderr and to syslog.
To view the messages in syslog:
journalctl -t fmd-server
less /var/log/syslog | grep fmd-serverThis project was funded through the NGI Mobifree Fund. For more details, visit our project page
FMD Server is published under GPLv3-or-later.