Once in a while, I want to try some idea to implement. Having background by developing mostly in .NET stack my choice is obviously .NET Core. I always have at hand couple of Linux servers: one is in DigitalOcean, another one is MSI Cubi N under my TV set. Hence, my Linux horses will run .NET Core app.
My yet another brilliant idea is waiting for implementation. Wait a minute! It will not happen without a continuous integration server which is triggered by GitHub in order to prepare a release package. And, don’t forget about a continuous delivery server, how can we deploy without it? Probably, it is even better to set up Kubernetes cluster. Right? No way! That’s not for me. I would like to have something as simple as possible. KISS principle after all!
How minimal deployment script will look like? I’m going to deploy to my MSI Cubi N that has 192.168.2.4. After a couple of evenings googling and debugging the script is ready. It uses rsync in order to upload only changed files, systemd for running the console app as service and restarting in case of failure.
#!/bin/bash
ssh [email protected] 'bash -s' <<'ENDSSH'
printf "Stopping service...\n"
systemctl stop HelloSshDeploy
printf "Service is "
systemctl is-active HelloSshDeploy
mkdir -p /apps/HelloSshDeploy
ENDSSH
printf "Uploading new version of service...\n"
rsync -v -a ./bin/Release/netcoreapp2.2/ubuntu.16.04-x64/publish/ [email protected]:/apps/HelloSshDeploy/
ssh [email protected] 'bash -s' <<'ENDSSH'
chmod 777 /apps/HelloSshDeploy/Gaev.Blog.Examples.HelloSshDeploy
if [[ ! -e /etc/systemd/system/HelloSshDeploy.service ]]; then
printf "Installing service...\n"
cat > /etc/systemd/system/HelloSshDeploy.service <<'EOF'
[Unit]
Description=HelloSshDeploy
After=network.target
[Service]
WorkingDirectory=/apps/HelloSshDeploy
ExecStart=/apps/HelloSshDeploy/Gaev.Blog.Examples.HelloSshDeploy
Restart=always
KillSignal=SIGINT
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable HelloSshDeploy
fi
printf "Starting service...\n"
systemctl start HelloSshDeploy
printf "Service is "
systemctl is-active HelloSshDeploy
ENDSSH
My .NET Core console app is super small. I’m using Console.CancelKeyPress here to respect Ctrl + C and SIGINT signal which is sent by Linux to stop the console app.
class Program
{
static async Task Main(string[] args)
{
var cancellation = new CancellationTokenSource();
Console.CancelKeyPress += (_, e) => { e.Cancel = true; cancellation.Cancel(); };
using (var logger = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.File("HelloSshDeploy.log")
.CreateLogger())
await RunApplication(logger, cancellation.Token);
}
static async Task RunApplication(Logger logger, CancellationToken cancellation)
{
logger.Information("Hello World!");
try
{
await Task.Delay(Timeout.Infinite, cancellation);
}
catch (TaskCanceledException) { }
logger.Information("Goodbye World!");
}
}
Prerequisites for deployment over SSH
Linuxmachine itself: for instance, you can start from $5/mo machine by DigitalOcean;- ssh & rsync on your machine must be installed. For
Windowsusers, the easiest way is to installUbuntuforWindows 10via Windows Subsystem for Linux; - password-less
SSHlogin must be configured in targetLinuxmachine. ssh-copy-id to the rescue; - root login over SSH must be enabled in target
Linuxmachine.
Finally, it takes 4 seconds in order to deploy. See the execution result of the following commands:
./make.sh
./deploy.sh

See source code here Gaev.Blog.Examples.HelloSshDeploy.