Skip to content

About

Read-only mirror of dcomms-app

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

34 Commits

Folders and files

Repository files navigation

dComms App

A Flutter app that installs and manages a dcommsctl host for people who are not sysadmins. It takes you from "I have a VPS (or a DigitalOcean or Yandex Cloud account)" to "here is my Dawa URL and my running apps", with no terminal work.

It runs on Linux, macOS, Windows, Android and iOS.

What it does

There are four ways to add a server:

Mode You provide Result
SSH host, port, user, password or private key The app runs the installer over SSH and saves the server as managed (live status)
DigitalOcean a personal access token The app creates a droplet with a generated SSH key, installs through cloud-init, and saves it as managed
Yandex Cloud a service account authorized key (JSON) The app creates a VM with a generated SSH key, installs through cloud-init, and saves it as managed
Manual nothing; you run a curl … | sudo bash one-liner yourself You paste the output back and the server is saved as unmanaged (access details only)

All four use the same install script, generated by lib/install/remote_script.dart. The script:

  1. installs Docker,
  2. downloads the dcommsctl tarball and checks its SHA-256,
  3. unpacks it to /opt/dcomms,
  4. pulls the Dawa image and tags it dawa:latest,
  5. starts dcommsctl as a systemd service on 127.0.0.1:6006,
  6. sets up the firewall,
  7. prints an enrollment block that the app parses.

Managed servers are reached through an SSH tunnel to dcommsctl's JSON-RPC websocket. The daemon is never exposed publicly. Dawa is served at http://dawa.<ip-dashed>.sslip.io:8000 by default, or under a domain you choose.

See PLAN.md for the design, the security model and known issues.

Warning: dcommsctl's Dawa template still sets DEMO=true, so anyone who can reach a fresh Dawa can sign in as admin. The app shows this on the server detail screen.

Development

flutter pub get
flutter analyze
flutter test                 # offline suite
flutter run -d linux         # or macos / windows / an Android or iOS device

Layout

lib/
  config.dart        build-time settings: download URL, version, Dawa image
  install/           remote script, cloud-init + SSH / DigitalOcean / Yandex installers
  providers/         DigitalOcean and Yandex Cloud API clients
  ssh/               sessions, host-key pinning, key generation, tunnel
  rpc/               JSON-RPC client and dcommsctl API
  store/             server records (JSON) and secrets (secure storage)
  models/  ui/
test/
tool/e2e_server.sh   throwaway Debian + sshd container for the live test

Release artifacts the installer needs

The installer downloads two things that do not come from this repo. Both have to be published before the app can install a working server.

1. The dcommsctl tarball (from dcommsctl/)

dcommsctl reads conf_tmpl/ and scripts/ by relative path, so the artifact contains the whole runtime tree, not only the binary. release.sh builds it:

cd ../dcommsctl
./release.sh             # version from .dcomms-installation (first line)
./release.sh 0.0.2       # or set it explicitly
ARCHES=amd64 ./release.sh  # one architecture only

It writes to dcommsctl/dist/:

dcommsctl-<version>-linux-amd64.tar.gz
dcommsctl-<version>-linux-amd64.tar.gz.sha256
dcommsctl-<version>-linux-arm64.tar.gz
dcommsctl-<version>-linux-arm64.tar.gz.sha256

The binaries are static and the tarballs are reproducible (set SOURCE_DATE_EPOCH to pin the mtime). Before it finishes, the script repeats the installer's own download, verify and unpack checks on the output, so a broken artifact fails here and not on a user's server.

Check that the names match what this app asks for:

flutter test test/artifact_test.dart

Then upload all files in dist/ to a static HTTPS host, together in one directory. Both the .tar.gz and its .sha256 must be at the same base URL.

2. The Dawa image (from dawa/)

dcommsctl's Dawa compose template uses a bare image: dawa:latest. That image exists only on a machine that built it, so the installer pulls a registry image and tags it locally. Build and push it from dawa/:

cd ../dawa
docker build -t dawa .
docker login gitlab.equalit.ie
docker tag dawa gitlab.equalit.ie/dcomms/dawa:latest
docker push gitlab.equalit.ie/dcomms/dawa:latest

The server pulls this image without credentials, so the registry image must be public. To support arm64 servers, push a multi-arch image (for example, docker buildx build --platform linux/amd64,linux/arm64 -t <image> --push .).

Where to set the tarball address

Everything the installer downloads is set in lib/config.dart. These are compile-time constants, so rebuild the app after changing them.

Constant Set it to
kDcommsctlDownloadUrl The base URL where you uploaded dist/, without a trailing slash. Currently the placeholder https://downloads.dcomms.example/dcommsctl.
kDcommsctlVersion The <version> you passed to release.sh. It has to match the filenames exactly.
kDawaImage The registry image you pushed, e.g. gitlab.equalit.ie/dcomms/dawa:latest.

The installer then fetches:

<kDcommsctlDownloadUrl>/dcommsctl-<kDcommsctlVersion>-linux-<arch>.tar.gz
<kDcommsctlDownloadUrl>/dcommsctl-<kDcommsctlVersion>-linux-<arch>.tar.gz.sha256

<arch> is the server's dpkg --print-architecture (amd64 or arm64).

To release a new version, follow these steps in order:

  1. Run release.sh <version>.
  2. Upload dist/.
  3. Set kDcommsctlVersion (and the URL, if it changed).
  4. Run flutter test.
  5. Rebuild the app.

Testing against a real host

The offline suite does not touch SSH or Docker. To run a real install end to end, you need a local Docker daemon:

tool/e2e_server.sh up        # Debian 12 + systemd + sshd on port 2222

DCOMMS_E2E_HOST=127.0.0.1 DCOMMS_E2E_PORT=2222 \
DCOMMS_E2E_USER=root DCOMMS_E2E_PASSWORD=dcomms \
DCOMMS_E2E_DOWNLOAD_URL=<where dist/ is served> \
flutter test test/e2e_ssh_test.dart

tool/e2e_server.sh down

Without DCOMMS_E2E_DOWNLOAD_URL, the run stops at the download step on purpose. That run still covers connect, sudo, log streaming and the error block. To test without a public host, serve dist/ locally with python3 -m http.server -d ../dcommsctl/dist 8080, then use a URL the container can reach (for example, http://172.17.0.1:8080).

About

Read-only mirror of dcomms-app

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages