From 2b10336e6cd1d3f14935acddecd91347336a3736 Mon Sep 17 00:00:00 2001 From: Federico Ceratto Date: Sun, 25 Dec 2016 17:20:26 +0000 Subject: [PATCH] Created Tutorial: Creating a (micro) service (asciidoc) --- Tutorial:-Creating-a-(micro)-service.asciidoc | 169 ++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 Tutorial:-Creating-a-(micro)-service.asciidoc diff --git a/Tutorial:-Creating-a-(micro)-service.asciidoc b/Tutorial:-Creating-a-(micro)-service.asciidoc new file mode 100644 index 0000000..e65636a --- /dev/null +++ b/Tutorial:-Creating-a-(micro)-service.asciidoc @@ -0,0 +1,169 @@ +How to create a simple HTTP service and run it under systemd. + +Replace myservicename and myservicedir. + +Install the build requirements: +[source,bash] +---- +nimble install jester +---- + +=== Basic HTTP service + +Create myservice.nim : +[source,nim] +---- +import jester, posix, json +const config_file_name = "conf.json" + +# the "debug" and "info" macros from the logging module are not flushing the buffer + +proc log_debug(args: varargs[string, `$`]) = + debug args + fl.file.flushFile() + +proc log_info(args: varargs[string, `$`]) = + info args + fl.file.flushFile() + +onSignal(SIGABRT): + ## Handle SIGABRT from systemd + # Lines printed to stdout will be received by systemd and logged + # Start with "" from 0 to 7 + echo "<2>Received SIGABRT" + quit(1) + +# Add handlers for SIGSTOP, SIGQUIT as needed + +let conf = parseFile(config_file_name) +let fl = newFileLogger(conf["log_fname"].str, fmtStr = "$datetime $levelname ") +fl.addHandler + +include "templates/base.tmpl" +include "templates/home.tmpl" + +routes: + get "/": + resp base_page(generate_home_page()) + +when isMainModule: + log_info "starting" + runForever() + +---- + +=== Example templates + +Create /var/lib/myservicename/temaplates/base.tmpl +[source,nim] +---- +#? stdtmpl | standard +#proc base_page(content: string): string = +# result = "" + + + + myservicename + + + + + + + + +
+ ${content} +
+ + +---- + +Create /var/lib/myservicename/temaplates/home.tmpl +[source,nim] +---- +#? stdtmpl | standard +#proc generate_home_page(): string = +# result = "" +
Welcome to myservicename
+---- + + +=== Configure the running environment + +Create /lib/systemd/system/myservicename.service file. Configure CapabilityBoundingSet as needed. + +[source,ini] +---- +[Unit] +Description=myservicename +Documentation=man:myservicename +Documentation=https://github.com/REPLACEME/myservicename +After=network.target httpd.service squid.service nfs-server.service mysqld.service named.service postfix.service +Wants=network-online.target + +[Service] +Type=simple +WorkingDirectory=/var/lib/myservicedir/ +ExecStart=/usr/bin/stdbuf -oL /var/lib/myservicedir/myservicename +TimeoutStopSec=10 +KillMode=mixed +KillSignal=SIGTERM + +User=myservicename +#Group=myservicename +# Restart the daemon if crashes or is killed +Restart=always +RestartSec=2s +LimitNOFILE=65536 + +# Hardening +NoNewPrivileges=yes +CapabilityBoundingSet=CAP_DAC_READ_SEARCH +PrivateDevices=yes +PrivateTmp=yes +ProtectHome=yes +ProtectSystem=full +StandardOutput=syslog+console +StandardError=syslog+console +ReadWriteDirectories=/proc/self +ReadWriteDirectories=-/var/run + +[Install] +WantedBy=multi-user.target +---- + +Create /var/lib/myservicedir/conf.json +[source,json] +---- +{ + "log_fname": "/var/log/myservicename.log", +} +---- + +[source,bash] +---- +sudo adduser myservicename --system --home /var/lib/myservicedir +sudo touch /var/log/myservicename.log +sudo chown myservicename:myservicename /var/log/myservicename.log +sudo systemctl enable myservicename +sudo systemctl start myservicename +---- + + +=== Systemd watchdog + +To enable a watchdog, add "WatchdogSec=10s" to the service file. + +Install https://github.com/FedericoCeratto/nim-sdnotify + +[source,nim] +---- +import sdnotify +let sd = newSDNotify() +sd.notify_ready() +# Every 5 seconds in a dedicated thread: +sd.ping_watchdog() +---- +