REST API server based on Apache and backend Bash via cgi module for remote managment Linux 🐧 using curl or Invoke-WebRequest in Windows.
Implemented Linux service management via systemd (with systemctl
commands) using basic authorization.
Install an Apache server and jqlang for json
processing (in the example for Ubuntu/Debian):
apt install apache2 jq
The following described customization steps can be performed using the build script.
💡 Sudo privileges required
- Configure port
8443
(or use any other by specifying it inVirtualHost
):
cat /etc/apache2/ports.conf | sed -r "s/^Listen.+/Listen 8443/" > /etc/apache2/ports.conf
- Activate the HTTP
Basic Authentication
module and add a user (in the examplerest
and passwordapi
):
a2enmod auth_basic
htpasswd -b -c /etc/apache2/.htpasswd rest api
- Create a file at the path
/var/www/api/api.sh
and copy the contents of theapi.sh
script:
mkdir /var/www/api && touch /var/www/api/api.sh && chmod +x /var/www/api/api.sh
curl -s "https://raw.githubusercontent.com/Lifailon/bash-api-server/rsa/www/api/api.sh" > /var/www/api/api.sh
- Configure a VirtualHost (
/etc/apache2/sites-available/api.conf
) this way:
<VirtualHost *:8443>
ScriptAlias /api /var/www/api/api.sh
<Directory "/var/www/api">
Options +ExecCGI
AddHandler cgi-script .sh
AllowOverride None
Require all granted
</Directory>
<Location "/api">
AuthType Basic
AuthName "Restricted Area"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
SetHandler cgi-script
Options +ExecCGI
</Location>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
- Activate the module for working cgi-scripts, activate the created VirtualHost and start the server:
a2enmod cgi
a2ensite api.confs
systemctl restart apache2
- In order for the Apache server to be able to manage services, the
www-data
user must be granted the appropriate sudo permissions:
echo "www-data ALL=(ALL) NOPASSWD: /bin/systemctl start *, /bin/systemctl stop *, /bin/systemctl restart *" >> /etc/sudoers
Get the status of the service specified in the header (the example, cron):
curl -s -X GET http://192.168.3.101:8443/api/service/cron -u rest:api
{
"unit": "cron.service",
"load": "loaded",
"active": "active",
"sub": "running",
"description": "Regular background program processing daemon",
"uptime": "5h 1min",
"startup": "enabled"
}
Stop the service:
curl -s -X POST http://192.168.3.101:8443/api/service/cron -u rest:api -H "Status: stop"
{
"unit": "cron.service",
"load": "loaded",
"active": "inactive",
"sub": "dead",
"description": "Regular background program processing daemon",
"uptime": "108ms",
"startup": "enabled"
}
Start the service:
curl -s -X POST http://192.168.3.101:8443/api/service/cron -u rest:api -H "Status: start"
{
"unit": "cron.service",
"load": "loaded",
"active": "active",
"sub": "running",
"description": "Regular background program processing daemon",
"uptime": "104ms",
"startup": "enabled"
}
PowerShell (output in default object format):
$user = "rest"
$pass = "api"
$EncodingCred = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("${user}:${pass}"))
$Headers = @{"Authorization" = "Basic ${EncodingCred}"}
Invoke-RestMethod -Headers $Headers -Uri http://192.168.3.101:8443/api/service/cron
unit : cron.service
load : loaded
active : active
sub : running
description : Regular background program processing daemon
uptime : 41min
startup : enabled
List of services in HTML table format when accessed through a Web browser Chrome: