{"id":46274290,"url":"https://github.com/audioscavenger/dms-gui","last_synced_at":"2026-03-04T04:01:15.392Z","repository":{"id":319519872,"uuid":"1068561385","full_name":"audioscavenger/dms-gui","owner":"audioscavenger","description":"A graphical user interface for managing DMS (Docker-Mailserver). This portal aims to manage all aspects of DMS including email accounts, aliases, UI settings, indexes, etc. ","archived":false,"fork":false,"pushed_at":"2026-02-02T00:44:20.000Z","size":3182,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-02T10:34:06.161Z","etag":null,"topics":["api","docker","docker-compose","dovecot","email","gui","node-js","portal"],"latest_commit_sha":null,"homepage":"https://dms-gui-demo.doctusit.com","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/audioscavenger.png","metadata":{"files":{"readme":"README.dockerhub.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-02T15:10:11.000Z","updated_at":"2026-02-02T00:44:23.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/audioscavenger/dms-gui","commit_stats":null,"previous_names":["audioscavenger/dms-gui"],"tags_count":79,"template":false,"template_full_name":null,"purl":"pkg:github/audioscavenger/dms-gui","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/audioscavenger%2Fdms-gui","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/audioscavenger%2Fdms-gui/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/audioscavenger%2Fdms-gui/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/audioscavenger%2Fdms-gui/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/audioscavenger","download_url":"https://codeload.github.com/audioscavenger/dms-gui/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/audioscavenger%2Fdms-gui/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30071670,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-04T03:25:38.285Z","status":"ssl_error","status_checked_at":"2026-03-04T03:25:05.086Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","docker","docker-compose","dovecot","email","gui","node-js","portal"],"created_at":"2026-03-04T04:01:14.614Z","updated_at":"2026-03-04T04:01:15.377Z","avatar_url":"https://github.com/audioscavenger.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Docker Mailserver GUI\n[![Docker Pulls](https://img.shields.io/docker/pulls/audioscavenger/dms-gui)](https://hub.docker.com/r/audioscavenger/dms-gui)\n\nA graphical user interface for managing DMS ([Docker-Mailserver](https://github.com/docker-mailserver/docker-mailserver)) and other non-gui mailservers like Poste.io. This gui aims to manage all aspects of DMS including: email accounts, aliases, xapian indexes, DNS entries, and other stuff.\n\nIt relies on a generic REST API written in python, that you have to mount in DMS compose.\n\n## Features\n\n- 🌐 Multi-arch: x86_64 (amd64) + aarch64 (arm64)\n- 🔐 Login page, crypto-secure hashed passwords, HTTP-Only cookies\n- 📊 Dashboard with server status information\n- 👥 User management with roles for their mailboxes\n  - 👤 Profile page\n  - 📬 Mailbox account management\n  - 📧 Email alias management (includes regex)\n- 🐋 DMS (Docker-Mailserver) connection configuration\n  - 🗃️ Multiple-DMS ready!\n  - 🔑 REST API Key management for direct access\n- 🛢️ better-sqlite3 database!\n  - 🩹 database patch auto-upgrade\n- 🌐 Multilingual support (English, Polish)\n- 👌 Cutting edge Node.JS v24\n\n\n## Compatibility Chart\n\n| dms     | dms-gui | x86_64 | aarch64 | details |\n|---------|---------|--------|---------|---------|\n| v15.1.0 | v1.5 | ✔️ | ✔️ | dovecot 2.3 |\n| v16?    | ❌ | ❌ | ❌ | dovecot 2.4 |\n\n\n### FAQ\n\n* [x] How does dms-gui interact with DMS?\n\u003e Simply, by executing `system` and `doveadm` commands inside DMS, through a python REST API. \n\n* [x] How does dms-gui execute commands in DMS?\n\u003e Python REST API script and its loader are generated from dms-gui, and then mounted as a single volume in DMS compose, along with the exposed port. You don't need to alter `user-patches.sh` at all. The REST API script is conveniently placed in a folder that is mouted in DMS: `./config/dms-gui/`.\n\n* [x] How secure is this REST API?\n\u003e REST API Access security is handled with a key generated from dms-gui itself. The key is sent in query header of the http calls. Since the DMS REST API port is exposed on the docker network only, no one else has access to it.\n\n* [x] I don't trust you, can I see the python code for this REST API?\n\u003e Sure, it's in the `/backend/env.js` file.\n\n* [x] How about logon security?\n\u003e Top notch: best practice for React has been followed: CORS same-domain Strict + HTTPonly cookies + backend verification of credentials, zero trust of the frontend.\n\n* [x] Tell me more about logon security?\n\u003e Two 32 bits secrets are generated when container starts: one for generateToken (valid 1h) and the other for refreshToken (valid 7 days). Refresh tokens are saved in the db for each user and invalidated when container restarts, since the secrets have changed.\n\n* [x] Security really bothers me, anything more?\n\u003e Yes, the container relies on node-cron and restarts daily at 11PM to regenerate new secret keys. You can alter the schedule with the environment variable `DMSGUI_CRON`.\n\n* [x] How about password security?\n\u003e Standard practice: passwords are stored in a local sqlite3 db as separate salt and hash. We only force users to use 8+ characters.\n\n* [x] Can a linked mailbox user hack their way into admin or unauthorized commands?\n\u003e No, their credentials are set in the HTTPonly cookie and the backend only relies on its values to determine what's allowed.\n\n* [x] Can a user do path transversal or sql injections or anything to exploit this portal?\n\u003e No, sql commands are stored in a backend dictionary, and no frontend module can send sql commands directly. SQL is variabilized in the backend and cannot be injected. Routes are also protected following React best practices. The separation between frontend and backend is complete and interfaced with an API, just like Electron.js.\n\n* [x] What do users have access to, in this portal?\n\n| user / Access| password | Profile   | Dashboard | Accounts | Aliases | Logins | Settings | Backups | Imports |\n| -------------|----------|-----------|---------|----------|---------|----------|----------|---------|---------|\n| admins       | dms-gui  | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |\n| users        | dms-gui  | ✔️ | ✔️ | partial | partial | ❌ | ❌ | partial | ❌ |\n| linked users | DMS      | ✔️ | partial | ❌ | partial | ❌ | ❌ | partial | ❌ |\n\n* [x] Can normal users change their password?\n\u003e Yes, users can change both their dms-gui password in their profile, and each of the mailboxes they control under Accounts. Logon password in dms-gui is saved in the database. Mailbox-linked users can only change the mailbox password, and their logon is handled by DMS dovecot directly.\n\n* [x] Can users reset their forgotten password?\n\u003e Not yet, but it's coming.\n\n* [x] Is this project affected by React2Shell Critical Vulnerability (CVE-2025-55182)[https://www.cmu.edu/iso/news/2025/react2shell-critical-vulnerability.html]?\n\u003e No. This project has none of the React or 3rd party affected components like react-server-dom-turbopack, and is not even of the React versions affected. As I understand it, turbopack is another memory unsafe web bundler written in Rust, yet again.\n\n\n### Login page\n\nAs long as the default admin user (_admin_ / password=_changeme_) exist, you are greeted with this message:\n\n![Login](https://github.com/audioscavenger/dms-gui/blob/main/assets/dms-gui-Login.webp?raw=true)\n\n### Profile page\n\nThere you can change your dms-gui / DMS Dovecot password. Users managers of multiple mailboxes cannot change individual mailboxes yet.\n\n![Login](https://github.com/audioscavenger/dms-gui/blob/main/assets/dms-gui-Profile.webp?raw=true)\n\n### Logins Management\n\nLogins are 3 types:\n\n| type | perks | details |\n| -----|-------|---------|\n| admins | Administrator | Can even demote itself |\n| users | Can manage multiple mailboxes | Not admin, cannot change managed mailboxes, Authentication by dms-gui |\n| linked users | Can change their mailbox password | Authentication provided by DMS Dovecot |\n\n![Logins](https://github.com/audioscavenger/dms-gui/blob/main//assets/dms-gui-Logins-new-user.webp?raw=true)\n\nMailbox selection list comes from DMS directly. Password will be saved in both dms-gui and Dovecot in DMS, but Authentication for linked mailbox users is provided by DMS.\n\n![Logins](https://github.com/audioscavenger/dms-gui/blob/main//assets/dms-gui-Logins-new-linkbox.webp?raw=true)\n\nMailbox users are automatically created, based off the scan of DMS dovecot server. The mechanic does not check if mailboxes have been deleted, it only pulls the current list and update the local db.\n\n![Logins](https://github.com/audioscavenger/dms-gui/blob/main//assets/dms-gui-Logins-auto.webp?raw=true)\n\n### Accounts\n\nAlso called \"_emails_\", as per the DMS setup command to create new email boxes, I prefer calling them _mailboxes_. They are _Accounts_, that can receive/store/send emails.\n\nAccounts are automatically discovered and pulled from the local database for its speed. You can refresh the data manually with a simple click.\n\nCreating accounts from here currently calls the DMS `setup` via `docker.sock`, but soon will rely on dovecot 2.4 API calls instead. Passwords entered are also stored in the local db.\n\n![Accounts](https://github.com/audioscavenger/dms-gui/blob/main/assets/dms-gui-Accounts.webp?raw=true)\n\n### Aliases\n\nCurrently relying on DMS `setup` and a direct read of the `postfix-regexp.cf`file.\n\n![Aliases](https://github.com/audioscavenger/dms-gui/blob/main/assets/dms-gui-Aliases.webp?raw=true)\n\n### Settings\n\nMultiple sections to save UI settings, DMS REST API access, and show some internals + DMS environment values.\n\n![Settings](https://github.com/audioscavenger/dms-gui/blob/main/assets/dms-gui-Settings.webp?raw=true)\n\ndms-gui internals come from Node environment, and DMS values come from a mox of the `env` command and parsing dkim and dovecot configuration.\n\nSome environment values like FTS (Full Text Search) will enable some options on the _Accounts_ page (`reindex` for instance).\n\n![Settings](https://github.com/audioscavenger/dms-gui/blob/main/assets/dms-gui-ServerInfos.webp?raw=true)\n\n### Dashboard\n\nA dumb dashboard, but now you can click the cards and navigate to the section selected.\n\n![Dashboard](https://github.com/audioscavenger/dms-gui/blob/main/assets/dms-gui-Dashboard.webp?raw=true)\n\n## Requirements\n\n- [Docker-Mailserver](https://docker-mailserver.github.io/docker-mailserver/latest/) (installed and configured)\n- dms-gui definition in DMS compose, will extra port, volumes, and environment variables in DMS section\n\n## Project Structure\n\n- Node.js (v24 is embedded)\n- npm and dozens of packages\n\nThe application consists of two parts:\n\n- **Backend**: Node.js/Express API for communicating with Docker-Mailserver\n- **Frontend**: React user interface with i18n support\n\n## Installation\n\nYou have nothing to install, this is an all-included docker image that provides a GUI for DMS.\n\nIf you want to develop/pull requests and test, see README.docker.md and each README under the subfolders `backend` and `frontend`.\n\n## Configuration\n\n`./config/dms-gui/` will host dms-gui.sqlite3 and its environment config file. This is a subfolder of the DMS `config` repository, for convenience; use any folder you want and update all the mounting points accordingly.\n\nRename `./config/dms-gui/.dms-gui.env.example` as `./config/dms-gui/.dms-gui.env` and update for your own environment:\n\n```\n###############################################################################\n## dms-gui Configuration: all is handled by React.\n## Only the defaults used in dms-gui will be mentionned here.\n###############################################################################\n## JWT_SECRET = secret for salting the cookies, regenerated during container start, before starting node\n## JWT_SECRET_REFRESH = secret for salting the refresh cookies, regenerated during container start, before starting node\n## Those keys cannot be defined anywhere else then during container start, and are secret as the name suggests\n## docker/start.sh creates them\n###############################################################################\n\n## Optional: Dev Environment\n# NODE_ENV=development\nNODE_ENV=production\n\n## Debugging\n# DEBUG=true\n\n## how long before rotation of the secrets:\nACCESS_TOKEN_EXPIRY=1h\nREFRESH_TOKEN_EXPIRY=1d\n\n## encryption options:\n## IV_LEN is the length of the unique Initialization Vector (IV) = random salt used for encryption and hashing\nIV_LEN=16\n## HASH_LEN is the length of the hashed keys for passwords\nHASH_LEN=64\n## AES_SECRET = encrypted data secret key, that one is set in the environment as well but must never change or you won;t be able to read your encrypted data anymore\n## generate it once and for all with node or openssl:\n##   openssl rand -hex 32\n##   node -e \"console.log(require('crypto').randomBytes(32).toString('hex'))\"\nAES_SECRET=replaceme\n## encrypted data algorithm\nAES_ALGO=aes-256-cbc\n## AES_HASH is the used to hash the secret key\nAES_HASH=sha512\n\n## utility paths for internal database\nDMSGUI_CONFIG_PATH=/app/config\nDATABASE=${DMSGUI_CONFIG_PATH}/dms-gui.sqlite3\n\n## Override the daily restart of the container, with this simple trick: default is 11PM\n## The container must restart regularly to regenerate the secret keys. Security first.\n##           ┌────────────── second (optional)\n##           │ ┌──────────── minute\n##           │ │ ┌────────── hour\n##           │ │ │  ┌──────── day of month\n##           │ │ │  │ ┌────── month\n##           │ │ │  │ │ ┌──── day of week\n##           │ │ │  │ │ │\n##           │ │ │  │ │ │\n##           * * *  * * *\nDMSGUI_CRON=\"* 1 23 * * *\"\n\n# make this a demo server\n# isDEMO=true\n\n# disable colors in backend logs, some terminals can't handle them\n# LOG_COLORS=false\n```\n\n### Environment Variables for dms-gui in .dms-gui.env\n\nAll is optional, as they will be superseeded by the ones defined and saved within dms-gui:\n\n- `DEBUG`: Node.js environment: (*production or development)\n- `ACCESS_TOKEN_EXPIRY`: lifetime of the generated HTTPonly token (1h)\n- `REFRESH_TOKEN_EXPIRY`: lifetime of the generated HTTPonly refresh token (1d)\n- `DMSGUI_CRON`: crontab format for daily restarts (\"* 1 23 * * *\")\n- `LOG_COLORS`: set false to disable colors in backend logs (*true)\n- `isDEMO`: set false to disable colors in backend logs (*false)\nThe ones you should never alter unless you want to develop:\n\n- `PORT_NODEJS`: Internal port for the Node.js server (*3001)\n- `API_URL`: defaults to `http://localhost:3001`\n- `NODE_ENV`: Node.js environment: (*production or development)\n\n### Environment Variables for dms REST API in compose\n\n- `DMS_API_HOST`: defaults to 0.0.0.0\n- `DMS_API_PORT`: defaults to 8888\n- `DMS_API_KEY`: format is \"dms-uuid\" or whatever you like, must be created in dms-gui first\n- `DMS_API_SIZE`: defaults to 1024\n- `LOG_LEVEL`: defaults to 'info', value is set in your `mailserver.env`\n\n## Language Support\n\nThe application supports multiple languages throught i18n.js:\n\n- English\n- Polish (out of date)\n\nLanguages can be switched using the language selector in the top navigation bar.\n\n## Docker Deployment\n\nThere are two ways to deploy using Docker:\n\n### Option 1: Docker Compose with dms + proxy (Recommended)\n\n#### Compose for dms + dms-gui\n\nSample extract from `docker-compose.yml`, rename `dms` to the actual name of your docker-Mailserver container!\n\n```yaml\n---\nservices:\n  dms:\n    \u003cyour dms compose here\u003e\n    ...\n    environment:\n      # DMS_API_HOST:           # defaults to 0.0.0.0\n      DMS_API_PORT: 8888        # defaults to 8888, must match what you se in dms-gui/Settings\n      DMS_API_KEY: uuid-random  # key generated by you or dms-gui\n      # DMS_API_SIZE: 1024      # defaults to 1024\n    expose:\n      - \"8888\"                  # local python REST API, must match what you se in dms-gui/Settings\n    volumes:\n      ...\n\n      # 1. you MUST create a subfolder \"dms-gui\" under your DMS config folder and mount in in the dms-gui section as \"/app/config/\"\n      # 2. AFTER you create and inject the API key under dms-gui Settings page, enable the API by uncommenting the line below and restart DMS\n      # 2. DO NOT enable the mount below until you created and saved the API in dms-gui, as the file is read only and cannot be created otherwise\n      - ./config/dms-gui/rest-api.conf:/etc/supervisor/conf.d/rest-api.conf:ro\n      \n    networks:\n      frontend:                 # same network as dms-gui\n  \n  gui:\n    container_name: dms-gui\n    hostname: dms-gui\n    image: audioscavenger/dms-gui:latest\n    restart: unless-stopped\n    depends_on:\n      - dms\n\n    # Use this environment file or the environment section, or both:\n    # Note: the file is placed under DMS own config folder; \n    # if using another one you will need to mount both the api.conf and api.py files in DMS\n    env_file: ./config/dms-gui/.dms-gui.env\n    \n    environment:\n      - TZ=${TZ:-UTC}\n      \n      # Debugging\n      # - DEBUG=true\n\n    expose:\n      - 80                      # frontend\n      - 3001                    # /docs\n    \n    volumes:\n      - /etc/timezone:/etc/timezone:ro\n      - /etc/localtime:/etc/localtime:ro\n      # we are mounted under DMS own config folder:\n      - ./config/dms-gui/:/app/config/\n      \n    networks:\n      frontend:                 # same network as DMS\n\n# use the network of your choice, or default internal;\n# DMS and dms-gui must be on the same network to see each others\nnetworks:\n  frontend:\n    external: true\n    name: frontend\n```\n\n**Note:** Replace `dms` with the name of your docker-mailserver container.\n\n**Note:** Replace `frontend` with the name of the external network your proxy also uses\n\n#### Reverse proxy\n\nWe recommend this reverse proxy for its simplicity: [swag](https://docs.linuxserver.io/general/swag/).\n\nSample proxy configuration:\n\n```nginx\nserver {\n    listen 443 ssl;\n   listen 443 quic;\n    listen [::]:443 ssl;\n   listen [::]:443 quic;\n  \n  server_name dms.*;\n\n  # swagger API docs\n  location /docs {\n\n    # enable the next two lines for http auth\n    auth_basic \"Restricted\";\n    auth_basic_user_file /config/nginx/.htpasswd;\n\n    include /config/nginx/proxy.conf;\n    include /config/nginx/resolver.conf;\n\n    set $upstream_app dms-gui;\n    set $upstream_port 3001;\n    set $upstream_proto http;\n    proxy_pass $upstream_proto://$upstream_app:$upstream_port;\n\n  }\n\n  location / {\n\n    # enable the next two lines for http auth (use you own)\n    # auth_basic \"Restricted\";\n    # auth_basic_user_file /config/nginx/.htpasswd;\n\n    include /config/nginx/proxy.conf;\n    include /config/nginx/resolver.conf;\n\n    set $upstream_app dms-gui;\n    set $upstream_port 80;\n    set $upstream_proto http;\n    proxy_pass $upstream_proto://$upstream_app:$upstream_port;\n\n  }\n\n}\n```\n\nYou can and _should_ add a form of authentication at the proxy level, unless you totally trust React AuthContext and its implementation (which I don't).\n\n\n### Option 2: Manual using the pre-built image from Docker Hub\n\nUntested, sample below is missing lots of variables, and I don't care since you are supposed to use compose.\n\n```bash\ndocker run -d \\\n  --name dms-gui \\\n  --env-file ./config/dms-gui/.dms-gui.env \\\n  -p 127.0.0.1:80:80 \\\n  -p 127.0.0.1:3001:3001 \\\n  -v /var/run/docker.sock:/var/run/docker.sock:ro \\\n  -v /etc/timezone:/etc/timezone:ro \\\n  -v /etc/localtime:/etc/localtime:ro \\\n  -v./config/dms-gui/:/app/config/ \\\n  audioscavenger/dms-gui:latest\n```\n\n**Note:** Replace `dms` with the name of your docker-mailserver container.\n\n## Docker Features\n\n- Single container with both frontend and backend\n- Communication with docker-mailserver via Docker API\n- Minimal configuration (just set the container name)\n- optional Nginx to serve the React frontend and proxies API requests with http, disabled in Dockerfile\n\nFor detailed Docker setup instructions, please refer to:\n- [README.docker.md](README.docker.md) - Detailed Docker setup guide\n- [README.dockerhub.md](README.dockerhub.md) - Docker Hub specific information\n\n## Available endpoints (non exhaustive)\n\nSubject to heavily change over time, please use https://dms.domain.com/docs for current list.\n\n- `GET /api/status` - Server status\n- `GET /api/infos` - Server environment\n- `GET /api/settings` - Get settings\n- `GET /api/configs` - Get all config names in config table\n- `GET /api/roles` - Get a login's roles\n- `POST /api/envs` - Get DMS environment\n- `POST /api/settings` - Save settings\n- `GET /api/logins` - Get login\n- `POST /api/logins` - Add login\n- `PATCH /api/logins` - Update a login\n- `DELETE /api/logins` - delete login\n- `POST /api/loginUser` - login user true/false\n- `POST /api/logout` - logout\n\n- `PUT /api/doveadm` - send doveadm commands\n- `GET /api/accounts` - List email accounts\n- `POST /api/accounts` - Add a new account\n- `DELETE /api/accounts` - Delete an account\n- `PATCH /api/accounts` - Update account password\n- `GET /api/aliases` - List aliases\n- `POST /api/aliases` - Add a new alias\n- `DELETE /api/aliases` - Delete an alias\n- `GET /api/domains` - Get domains detected\n\n- `POST /api/getCount` - Get row count from a table\n- `POST /api/initAPI` - Create DMS API files and key\n- `POST /api/kill` - Reboot dms-gui\n\n### Swagger API docs\n\nOAS description of all API endpoints is available at:\n* using compose + proxy: http://localhost/docs or https://dms.domain.com/docs (with proxy)\n* using raw ports: http://localhost:3001/\n\n![API](https://github.com/audioscavenger/dms-gui/blob/main/assets/dms-gui-docs.webp?raw=true)\n\u003c!--\n![API](/assets/dms-gui-docs.webp?raw=true)\n--\u003e\n\n\n### API call Example:\n\n```shell\ncurl -sSL https://dms.domain.com/api/status\n```\n\nResult:\n\n```json\n{\n  \"status\": {\n    \"status\": \"running\",\n    \"error\": \"\",\n  },\n  \"resources\": {\n    \"cpuUsage\": 0.0051578073089701,\n    \"memoryUsage\": 200925184,\n    \"diskUsage\": \"N/A\"\n  }\n}\n```\n\n\n## Behind the Scenes\n\n### REST API\n\nThe REST API injected into DMS is *generic*: all it does is listen for POST requests, verify the KEY passed in the Authorization header, execute the system command passed in the body, and return the result in json format. You can use it free of charge in any other container having python3.\n\nIt's started as a deamon by simply mounting this supervisor service inside DMS, and shall be placed in a subfolder named `dms-gui` under the `config` folder of DMS. dms-gui creates both those files when you generate the API key in Settings, and only the supervisor conf shall be mounted in DMS compose:\n\n`./config/dms-gui/rest-api.conf:/etc/supervisor/conf.d/rest-api.conf:ro`\n\nThe supervisor code is pretty generic:\n\n```\n[program:rest-api]\nstartsecs=1\nstopwaitsecs=0\nautostart=true\nautorestart=true\nstdout_logfile=/var/log/supervisor/%(program_name)s.log\nstderr_logfile=/var/log/supervisor/%(program_name)s.log\ncommand=/usr/bin/python3 /tmp/docker-mailserver/dms-gui/rest-api.py\n```\n\nThis REST API logs what it does in `logs/supervisor/rest-api.log` like any other supervisor service, and I have found that `PYTHONUNBUFFERED=1` will not print the messages in the docker log when run as a daemon.\n\nTo use it with a Node.js client, it's pretty basic and simple:\n\n```js\nconst DMS_API_KEY = 'dms-uuid';\nconst jsonData = {\n  command: 'ls -l /some/folder',\n  timeout: 4,\n  };\nconst response = await postJsonToApi(`http://dms:8888`, jsonData, DMS_API_KEY);\n\nexport const postJsonToApi = async (apiUrl, jsonData, Authorization) =\u003e {\n  try {\n    const response = await fetch(apiUrl, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n        'Authorization': Authorization\n      },\n      body: JSON.stringify(jsonData),\n    });\n    if (!response.ok) {\n      \u003cyour error handling here\u003e\n    }\n    return await response.json(); // Parse the JSON response\n\n  } catch (error) {\n    \u003cyour error handling here\u003e\n  }\n}\n```\n\nSample of a response from the REST API:\n\n```\nResponse {\n  status: 200,\n  statusText: 'OK',\n  headers: Headers {\n    server: 'BaseHTTP/0.6 Python/3.11.2',\n    date: 'Sun, 21 Dec 2025 05:35:39 GMT',\n    'content-type': 'application/json'\n  },\n  body: ReadableStream { locked: false, state: 'readable', supportsBYOB: true },\n  bodyUsed: false,\n  ok: true,\n  redirected: false,\n  type: 'basic',\n  url: 'http://dms:8888/'\n}\n```\n\nFormat of the json returned from the response by `postJsonToApi`:\n\n```json\n{\n  error: \u003cerror\u003e,\n  returncode: 0,\n  stdout: \u003cstdout\u003e,\n  stderr: \u003cstderr\u003e\n}\n```\n\nCannot be simpler then that, and super secure since the script also controls the maximum size of the payload received in the POST request. The API key is added manually as an environment variable in DMS compose.\n\n### Logging\n\nFormatted logging with colors, that actually helps!\n![Logins](https://github.com/audioscavenger/dms-gui/blob/main/assets/dms-gui-logs.webp?raw=true)\n\n## Development\n\n### Automatic Formatting\n\nAbsolutely unnecessary, but this project uses [Prettier](https://prettier.io/) for consistent code formatting. Configuration is defined in the root `.prettierrc.json` file.\n\nFormatting was automatically applied to staged files before each commit using [Husky](https://typicode.github.io/husky/) and [lint-staged](https://github.com/okonet/lint-staged). This ensured that all committed code adheres to the defined style guide. I gave up using this as VScode does a fantastic job.\n\n### Manual Formatting\n\nYou can also manually format the code using the npm scripts available in both the `backend` and `frontend` directories:\n\n```bash\n# Navigate to the respective directory (backend or frontend)\ncd backend # or cd frontend\n\n# Format all relevant files\nnpm run format\n\n# Check if all relevant files are formatted correctly\nnpm run format:check\n```\n\n### Backend\n\n```bash\ncd backend\nnpx npm-check-updates -u\nnpm install\nnpm audit fix\n```\n\n### Frontend\n\n```bash\ncd frontend\nnpx npm-check-updates -u\nnpm install\nnpm audit fix\n```\n\nAfter running both parts, the application will be available at http://localhost:3001\n\n## License\n\nAGPL-3.0-only\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faudioscavenger%2Fdms-gui","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faudioscavenger%2Fdms-gui","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faudioscavenger%2Fdms-gui/lists"}