Kill your terminal and a backgrounded Twisted app can vanish with it if you launch it the wrong way, taking its logs with it. This guide starts a Twisted application from a Python application file, keeps it in the foreground while testing, and sends its logs somewhere you can actually inspect them. The same workflow also covers an existing .tap file.
Allow about fifteen minutes if the application already exists. You need the python3-twisted package, a readable application file, and a port or other resource that the application can use. The examples here use Twisted 24.3.0 from Ubuntu package python3-twisted 24.3.0-1ubuntu0.2.
This guide starts and stops a process. It does not install a service unit, change firewall rules, or edit the application: those are separate operational decisions.
Confirm which executable will run first. This is an ordinary read-only check and does not need elevated privileges:
$ command -v twistd3
/usr/bin/twistd3
$ twistd3 --version
twistd (the Twisted daemon) 24.3.0
The executable identifies itself as twistd, even when invoked through the twistd3 name. Its job is to read a twisted.application.service.Application from a file and run it. Check the available reactor names before selecting one:
$ twistd3 --help-reactors
asyncio asyncio based reactor
default A reasonable default: poll(2) if available, otherwise select(2).
epoll epoll(4) based reactor.
poll poll(2) based reactor.
select select(2) based reactor.
Your list may include platform-specific entries. Use a name printed by this command, not one copied from a different operating system.
For a Python application file, the file must define a variable named application. The -y or --python option selects that file and implies --no_save, so twistd3 will not save shutdown state for this launch.
# /path/to/application.py
application = build_application()
Replace build_application() with the application construction used by your project. This snippet is only the required variable shape, not a complete Twisted server.
If you already have a TAP file, use -f instead. With no input option, twistd3 looks for twistd.tap in its working directory. An AOT Python source file uses -s, and the manpage calls its format .tas. Do not mix two different input formats into the same command while troubleshooting: -y overrides -f.
Checkpoint: make sure the selected file exists and is readable before starting a service.
$ test -r /path/to/application.py && echo "application file is readable"
application file is readable
Use --nodaemon while testing: it keeps the process attached to your terminal, so import errors and startup messages are visible immediately. The command below also writes the log to standard output with --logfile=-:
$ twistd3 --nodaemon --python /path/to/application.py --logfile=-
2026-09-27 15:30:00+0100 [-] Log opened.
2026-09-27 15:30:00+0100 [-] Application starting
Exact timestamps and messages depend on the application. A command that remains attached is expected for a running service. If it exits, read the last lines carefully: a missing module, invalid application variable, occupied port, or permission error is more useful than repeatedly restarting it.
If your application needs a particular event loop, add a reactor selected from the earlier list, for example:
$ twistd3 --nodaemon --reactor=asyncio --python /path/to/application.py --logfile=-
Choose this only when the application expects that reactor. Changing it can alter networking behaviour and is not a general-purpose repair for a startup failure.
From a second terminal, check that the process is present and that the application responds on its documented interface. Use the application's own health check where one exists; a process listing is only a basic check:
$ pgrep -af 'twistd3.*application.py'
12345 /usr/bin/python3 /usr/bin/twistd3 --nodaemon --python /path/to/application.py --logfile=-
Return to the terminal running twistd3 and press Ctrl-C. The manpage documents SIGINT as the clean shutdown signal. Wait for the shell prompt before assuming the process has stopped:
^C
$ pgrep -af 'twistd3.*application.py' || echo "twistd3 is stopped"
twistd3 is stopped
This foreground test changes no persistent configuration. If the application created temporary files or changed its own data, recover those according to that application's documentation.
Once foreground operation is understood, let twistd3 daemonise. Set an explicit run directory and log path rather than relying on the defaults, which are the current directory and twistd.log. Create the destination first as the account that will run the process:
$ mkdir -p /path/to/twistd-run
$ twistd3 --python /path/to/application.py \
--rundir=/path/to/twistd-run \
--logfile=/path/to/twistd-run/application.log \
--pidfile=/path/to/twistd-run/application.pid
With no --nodaemon, twistd3 detaches and returns to the shell. Check the pid file and the log, then use the application-specific health check:
$ cat /path/to/twistd-run/application.pid
12345
$ tail -n 20 /path/to/twistd-run/application.log
2026-09-27 15:35:00+0100 [-] Log opened.
The default umask for a daemon is 0077, which makes newly created files private to the account. Keep that default unless you have a reviewed reason to change it. Do not use --euid casually: when running as root it retains the ability to regain privileges after binding a port.
Warning: binding a privileged port or changing uid and gid may require root, but running the whole application as root increases the impact of an application bug. Prefer a dedicated unprivileged account and a non-privileged port where the deployment permits it.
The manpage documents SIGUSR1 for log rotation. Send it to the pid recorded for this launch, not to an unrelated process:
$ pid=$(cat /path/to/twistd-run/application.pid)
$ kill -USR1 "$pid"
$ tail -n 5 /path/to/twistd-run/application.log
Recovery: if the process is no longer present, remove a stale pid file only after checking that its recorded number is not now being used by another process. A stale file is not evidence that it is safe to kill that number. If the service fails after a restart, return to the foreground command, use --logfile=-, and fix the first startup error before changing several options at once.
twistd3 --version identified the installed Twisted release.--python, --file, or --source) was checked before launch.--nodaemon and stopped with SIGINT.