Self-hosted service
karam-ajaj/atlas avatar
karam-ajaj/atlas

Atlas by karam-ajaj: Docker host scanning and network visualization for homelabs

Open-source tool for network discovery, visualization, and monitoring. Built with Go, FastAPI, and React, supports Docker host scanning.

1,325 stars75 forksJavaScriptMIT

At a glance

What is it?
Atlas scans Docker containers and neighboring hosts, stores the results in SQLite, and draws them as an interactive graph. It is aimed at homelab and small-infrastructure operators who want a self-hosted map, not at anyone who needs agent-based monitoring.
Who is it for?
Adopt Atlas if you run a homelab or a small Docker Swarm and want a self-hosted map of containers and neighboring hosts without deploying agents. Do not adopt it if you need per-container CPU and memory metrics, an agent-based collector, or a multi-tenant deployment with more than one admin account, since the README describes a single admin user.
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 88 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

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

Editorial analysis

The gap Atlas fills: containers and hosts on one map

Most monitoring stacks assume you will install an agent inside each workload. Atlas takes the opposite route. It reaches out from a single container, asks the Docker socket what is running on the host, and then probes the surrounding subnets for anything else that answers. The result is one inventory that mixes container metadata with externally discovered hosts.

The README lists three functions: scanning Docker containers, scanning local and neighboring hosts, and visualizing the data in real time. The container scan extracts IP addresses, MAC addresses, open ports, network names, and OS type from image metadata. The README is explicit that multiple IPs and multiple MACs per container are supported and that each network interface is tracked separately. That detail matters for anyone running Compose or Swarm services that attach to more than one network, where a single container can hold several addresses at once.

The audience is narrow and identifiable: homelab operators, small DevOps teams, and anyone running Docker on a machine that also sits on a LAN with printers, NAS boxes, and other appliances. If your estate is entirely cloud-native and your workloads are ephemeral, the host-discovery half of Atlas has little to scan.

Architecture: a Go scanner, a FastAPI backend, and Nginx in one image

The Dockerfile shows three cooperating pieces. Stage one builds a Go binary named atlas from the sources in config/atlas_go. Stage two starts from python:3.11-slim, installs nginx, nmap, traceroute, ping, nbtscan, sqlite3, net-tools, curl, jq, and docker.io, then installs FastAPI, Uvicorn, and protobuf with pip. The Go binary is copied to /config/bin/atlas, shell scripts to /config/scripts, and the static frontend to /usr/share/nginx/html.

The container starts through /config/scripts/atlas_check.sh, which the Dockerfile describes as initializing the database, running scans, and launching FastAPI and Nginx. The Go CLI handles initdb, which creates a SQLite database with the required schema. So the data path is: Go binary writes findings into SQLite, FastAPI reads that database and exposes it over HTTP, and Nginx serves the React frontend and proxies API calls. The README notes that the API is reachable both on the exposed API port and through the UI port via the Nginx configuration.

Two ports are declared, 8888 for the UI and 8889 for the API. The README warns that the deployment example uses --network=host, which is why those ports are configurable through environment variables rather than published with -p. The tooling list also tells you what the scanner actually does: nmap for port and OS fingerprinting, nbtscan for NetBIOS name resolution, ping and traceroute for reachability. Nothing here is agent-based, and nothing is installed on the scanned hosts.

Installing Atlas and running a first scan

Atlas ships as a container image, keinstien/atlas, with a tag placeholder in the README example. The command below is the documented deployment form. It needs host networking, two Linux capabilities, and a mount of the Docker socket, because the container scan reads container metadata through that socket.

bash
docker run -d \
  --name atlas \
  --network=host \
  --cap-add=NET_RAW \
  --cap-add=NET_ADMIN \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e ATLAS_UI_PORT='8884' \
  -e ATLAS_API_PORT='8885' \
  -e ATLAS_ADMIN_USER='admin' \
  -e ATLAS_ADMIN_PASSWORD='change-me' \
  -e ATLAS_AUTH_TTL_SECONDS='86400' \
  -e FASTSCAN_INTERVAL='3600' \
  -e DOCKERSCAN_INTERVAL='3600' \
  -e DEEPSCAN_INTERVAL='7200' \
  -e SCAN_SUBNETS="192.168.1.0/24,10.0.0.0/24" \
  keinstien/atlas:{tag}

After the container is up, the UI is served on the port you set in ATLAS_UI_PORT. With the defaults that is http://localhost:8888, and the API documentation lives at http://localhost:8888/api/docs when reached through Nginx, or on the API port directly. The README gives the default credentials for the public demo as admin and change-me, which is a clear signal that any real deployment should set ATLAS_ADMIN_PASSWORD to something else, or leave it unset to disable authentication entirely.

If SCAN_SUBNETS is not set, Atlas auto-detects the local subnet. Setting it explicitly is the way to cover more than one network, and the README shows a comma-separated list such as 192.168.1.0/24,10.0.0.0/24. Scan intervals are set at startup and the README states they can also be changed later from the Scripts Panel in the UI, or a scan can be triggered manually through the UI or the API. The scheduler starts with the container and runs in the background.

Authentication is optional and off by default. When ATLAS_ADMIN_PASSWORD is set, the UI shows a login gate before rendering any data, and the README says core endpoints (hosts, external, scripts, logs, scheduler, containers) then require a token. The auth surface is four endpoints: GET /api/auth/enabled, POST /api/auth/login, GET /api/auth/me, and POST /api/auth/logout. If you script against the API, the login call returns a bearer token that the other endpoints expect.

What Atlas does not do, and where it breaks down

Atlas is a discovery and mapping tool, not a metrics platform. Nothing in the README describes collecting CPU, memory, disk, or per-container resource usage over time. If you need time-series graphs of container load, this is the wrong tool and you will end up running something else beside it.

The privilege requirements are the second constraint. The documented deployment asks for --network=host, NET_RAW, NET_ADMIN, and a bind mount of /var/run/docker.sock. That combination gives the container broad access to the host network stack and to the Docker daemon. On a personal homelab that may be an acceptable trade. On a shared or regulated host it is a decision that needs to be made deliberately, and the README does not offer a reduced-privilege mode.

Authentication is single-user. The README describes ATLAS_ADMIN_USER as the admin username for login and notes it is a single user. There is no mention of roles, per-user accounts, or audit trails, so Atlas should not be exposed to the internet as a multi-user service. The public demo exists, but the README does not describe how that demo is isolated.

Finally, the documentation has gaps. The README does not document rollback or downgrade steps between releases, and it does not describe what happens to the SQLite database when the container is replaced. The repository does contain a MIGRATION_GUIDE.md at the top level, so upgrade guidance exists somewhere, but the README itself does not summarize it. Treat the database volume as something you need to plan for yourself.

Atlas compared with agent-based monitoring and with Nmap alone

The obvious alternative for the discovery half is Nmap by itself. Atlas installs nmap inside its image, so in a sense it wraps it. The difference is what happens after the scan: Nmap prints results, while Atlas persists them to SQLite, schedules repeat scans at FASTSCAN_INTERVAL, DOCKERSCAN_INTERVAL, and DEEPSCAN_INTERVAL, and renders them as a graph and a table in a browser. If you only need an occasional port listing from a shell, Nmap alone is lighter and needs no socket mount. If you want a persistent, always-current map, Atlas adds the storage and presentation layer that Nmap deliberately leaves out.

The other alternative is an agent-based monitoring system such as Prometheus with node_exporter and cAdvisor. That approach gives you metrics, alerting, and long-term retention, at the cost of running an exporter on every host and container you care about. Atlas needs nothing installed on the scanned machines, which is exactly why it works on devices you cannot modify, such as a managed switch or an appliance. The trade is depth: you get presence, addresses, ports, and OS fingerprints, not utilization.

A third option is Docker's own tooling. docker network inspect and docker ps give you container addresses on demand, but they say nothing about the rest of the subnet. Atlas merges the two views, which is the specific thing the README claims as its purpose.

Release cadence, licence, and what upgrading costs

The repository is not archived, and the last push was on 2026-07-05. Releases are tagged frequently relative to their size: 3.2.29 in October 2025, 3.3.0 at the end of October 2025, and 3.3.4 in February 2026. That pattern suggests small, incremental changes rather than long release trains, and the version numbers confirm it. The README does not describe a stable or LTS branch, so pinning a specific tag in the docker run command is the only upgrade control the documentation offers.

The project is MIT licensed. In practice that means you can use, modify, and redistribute it, including in commercial settings, provided the copyright notice and permission notice are preserved. It also means there is no warranty, which for a tool that mounts the Docker socket and scans your network is worth understanding before you rely on it. This is a description of the licence text, not legal advice; if the deployment is commercial, have someone check the terms.

Upgrade cost is dominated by the database. The README does not document a rollback path, and the container's SQLite file is the entire state of the tool. Before changing tags, the concrete thing to do is copy whatever volume or bind mount holds the database, then pull the new tag. MIGRATION_GUIDE.md in the repository is the file to read first, since the README does not cover schema changes between versions.

Editorial conclusion

Adopt Atlas if you run a homelab or a small Docker Swarm and want a self-hosted map of containers and neighboring hosts without deploying agents. Do not adopt it if you need per-container CPU and memory metrics, an agent-based collector, or a multi-tenant deployment with more than one admin account, since the README describes a single admin user. Before deploying, verify that your host allows NET_RAW and NET_ADMIN, that the Docker socket mount is acceptable to you, and that your SCAN_SUBNETS value covers the networks you actually want mapped.

Frequently asked questions

How do I install Atlas?

Atlas is distributed as a Docker image and the README gives a single docker run command that uses host networking, adds NET_RAW and NET_ADMIN, mounts /var/run/docker.sock, and sets ports and scan intervals through environment variables. The image tag is shown as a placeholder, keinstien/atlas:{tag}, so you choose the version yourself. The container starts through /config/scripts/atlas_check.sh, which initializes the database and launches FastAPI and Nginx.

Is authentication enabled by default in Atlas?

No. The README states that Atlas authentication is optional and disabled by default, and that setting ATLAS_ADMIN_PASSWORD enables it. When enabled, the UI shows a login gate before rendering data and core endpoints require a bearer token obtained from POST /api/auth/login.

Which subnets does Atlas scan?

The SCAN_SUBNETS environment variable takes a comma-separated list such as 192.168.1.0/24,10.0.0.0/24. If it is not set, the README says Atlas auto-detects the local subnet.

What ports does Atlas use by default?

The Dockerfile sets ATLAS_UI_PORT to 8888 and ATLAS_API_PORT to 8889 as defaults, and both are exposed. The README notes that the API documentation is reachable both on the API port and through the UI port via the Nginx configuration.

Does Atlas collect CPU and memory metrics from containers?

The README does not describe resource metrics collection. The container scan extracts IP addresses, MAC addresses, open ports, network names, and OS type from image metadata, and the host scan covers reachability, OS fingerprints, MACs, and open ports.

Official sources

  1. karam-ajaj/atlas on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
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/karam-ajaj-atlas.svg)](https://hysenlabs.com/projects/karam-ajaj-atlas)