Table of Contents
Custom Services (Bring-Your-Own)
DECNET ships 25+ first-class service plugins (see
Services catalog), but you can add your own without
writing a plugin by declaring a [custom-<name>] section in the INI.
The source of truth is decnet/custom_service.py (the CustomService
class) and the [custom-*] branch of decnet/ini_loader.py.
How it works
At INI load time the parser scans every section starting with custom-:
# decnet/ini_loader.py
if section.startswith("custom-"):
s = cp[section]
svc_name = section[len("custom-"):]
image = s.get("binary", "")
exec_cmd = s.get("exec", "")
ports_raw = s.get("ports", "")
ports = [int(p.strip()) for p in ports_raw.split(",") if p.strip().isdigit()]
cfg.custom_services.append(
CustomServiceSpec(name=svc_name, image=image, exec_cmd=exec_cmd, ports=ports)
)
Each resulting CustomServiceSpec is wrapped into a CustomService
(subclass of BaseService) and registered dynamically at deploy time
(register_custom_service() in the service registry). Once registered, the
custom slug behaves like any built-in service — you can list it in a decky's
services= line and reference it in the --services CLI flag.
CustomService.compose_fragment() produces a Docker Compose fragment of the
shape:
image: <binary>
container_name: <decky>-<slug>
restart: unless-stopped
environment:
NODE_NAME: <decky>
LOG_TARGET: <optional, from --log-target>
command: [<tokens from exec=>] # only emitted if exec= is non-empty
Underscores in the custom name are converted to dashes in the container
suffix (slug = name.replace("_", "-")).
Note: CustomService.dockerfile_context() returns None, so DECNET will
not try to build the image. The image you name in binary= must be
pullable (public registry, or present in the local Docker daemon).
Accepted keys
| Key | Required | Meaning |
|---|---|---|
binary |
yes | Docker image reference, e.g. myorg/weirdapp:1.2.3. Becomes the container's image:. |
exec |
no | Command to run inside the container. Space-split into a list and emitted as Compose command:. If omitted, the image's default CMD/ENTRYPOINT is used. |
ports |
no | Comma-separated list of integer ports. Non-numeric tokens are silently dropped. Used by the deploy layer to expose/route the ports. |
There are no other keys. Anything else in the section is ignored by
ini_loader.py.
The custom service slug (the part after custom-) must not collide with a
built-in service name.
Minimal working example
Ship a lightweight HTTP echo server as a decoy on port 9000:
[general]
net = 192.168.1.0/24
gw = 192.168.1.1
interface = eth0
# Define the custom service
[custom-echoweb]
binary = ealen/echo-server:0.9.2
exec = node index.js
ports = 80
# Use it on a decky, alongside a built-in service
[decky-app01]
ip = 192.168.1.130
services = ssh, echoweb
nmap_os = linux
[decky-app01.ssh]
ssh_version = OpenSSH_8.9p1 Ubuntu-3ubuntu0.6
kernel_version = 5.15.0-91-generic
users = root:toor
Deploy:
sudo decnet deploy --config echo.ini --interface eth0 \
--log-target 192.168.1.200:5140
At deploy time, decky-app01 will get two containers: a standard ssh
decoy and a decky-app01-echoweb container running
ealen/echo-server:0.9.2 with command: ["node", "index.js"].
Caveats
- No per-service persona subsection is honoured for custom services — the
service_cfgargument inCustomService.compose_fragment()is accepted but ignored. If you need persona/override behaviour, write a real plugin. - No Dockerfile build step.
binary=is pulled as-is. - If
exec=is empty, nocommand:key is emitted — the image's default entrypoint runs. LOG_TARGETis injected into the container env only if a CLI--log-targetwas passed todecnet deploy; otherwise the custom service is responsible for its own logging.
See also:
DECNET
User docs
- Quick-Start
- Installation
- Requirements-and-Python-Versions
- CLI-Reference
- INI-Config-Format
- Custom-Services
- Services-Catalog
- Service-Personas
- Archetypes
- Distro-Profiles
- OS-Fingerprint-Spoofing
- Networking-MACVLAN-IPVLAN
- Deployment-Modes
- SWARM-Mode
- MazeNET
- Remote-Updates
- Environment-Variables
- Teardown-and-State
- Database-Drivers
- Systemd-Setup
- Logging-and-Syslog
- Service-Bus
- Web-Dashboard
- REST-API-Reference
- Mutation-and-Randomization
- Troubleshooting
Developer docs
DECNET — honeypot deception-network framework. Pre-1.0, active development — use with caution. See Sponsors to support the project. Contact: samuel@securejump.cl