Automating server-based deployments of the Contegra Internet Research Portal.
Installing Packages
Configuring and Managing Services
Setting the firewall
User-oriented NGINX Config
- name: CREATE WEB ROOT - Create new directory /usr/share/nginx/
ansible.builtin.file:
state: directory
path: /usr/share/nginx/web
- name: GROUP AND USER MANAGEMENT - Create the web group
ansible.builtin.group:
name: web
state: present
# - name: GROUP AND USER MANAGEMENT - create the web user
# ansible.builtin.command:
# cmd: adduser -G nginx -g web -d /usr/share/nginx/web --system --shell=/bin/false
- name: GROUP AND USER MANAGEMENT - Create "web" user
ansible.builtin.user:
name: web
system: true
group: nginx
groups: web
home: /usr/share/nginx/web
shell: /bin/false
- name: NGINX CONFIGURATION - Delete the old NGINX Config We're going to pyt one in-line
ansible.builtin.file:
path: /etx/nginx/nginx.conf
state: absent
- name: NGINX CONFIGURATION - Change web root to /usr/share/nginx/web
ansible.builtin.copy:
dest: /etc/nginx/nginx.conf
content: |
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
listen [::]:80;
server_name _;
root /usr/share/nginx/web;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
# Settings for a TLS enabled server.
#
# server {
# listen 443 ssl http2;
# listen [::]:443 ssl http2;
# server_name _;
# root /usr/share/nginx/web;
#
# ssl_certificate "/etc/pki/nginx/server.crt";
# ssl_certificate_key "/etc/pki/nginx/private/server.key";
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 10m;
# ssl_ciphers PROFILE=SYSTEM;
# ssl_prefer_server_ciphers on;
#
# # Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
#
# error_page 404 /404.html;
# location = /40x.html {
# }
#
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
# }
# }
}
- name: NGINX CONFIGURATION - Restart NGINX to catch the new configuration file
ansible.builtin.service:
name: nginx
state: reloaded
- name: NGINX CONFIGURATION - Touch sample index to verify functionality
ansible.builtin.copy:
dest: /usr/share/nginx/web/index.html
content: |
<h1> It Works!</h1>
Automating code deployment
To try and make this deployment as secure as possible, I am going to use Deployment Keys. I don’t want to have to worry about passwords in files, and I want things to remain easily auditable. So
Generating the Keypair
Generating a keypair is actually pretty straight forward, you use the ssh-keygen
command with default options. If your distribution is generating RSA keys, the algorithms for breaking RSA keys have been known for the past 25 years and ed25519 keys appear to be more secure and performant. The how and why of this is outside the scope of this blog post.
The only thing I’m going to do different is name these keys “DeploymentKeys” and create them without a passphrase. These keys will only be accessible “internally” and it obviously defeats the purpose of an automated deployment if I have to put a password in to use them. SO, this step looks like:
Nice, So keys are had. How do I get Gitlab to accept them?
Configuring Public Key into Gitlab
Like I stated above, I’m going to use Deploy Keys which will allow me to do password-less git pulls via ssh on a per-repo basis. I see myself creating per-app deployment keys, and then using that application-specific deployment key for deployments of any piece of the application.
To Add a key, I need to navigate to my repository, Research Portal , and access the repos settings from the left side navigation pane. In the settings view there will be a header called “Deploy Keys” and that’s where I’m going to add the PUBLIC KEY generated in the step above and I’ll set it to expire at the end of the year.
Configuring Private Key into Target Server
Noice, how do I test that? Let’s hop over to the test server and and try cloning with SSH
GitLab ain’t having it. That’s because the private key I need to auth ssh pulls isn’t on this server, let’s change that.
Typically you would just add the public key to a remote server so that you can use your private key on your local machine to initiate passwordless SSH sessions. But since this server is going to be the one fetching the code, initiating the ssh session, The private key needs to be on the system.
Since the playbook is running as root, I’m going to place the keys in .ssh/*
for the root account. I believe this will make it so that when the playbook , running as root via become
, reaches the step to clone the code. It should be initiating the session from the root account, so the root’s keystore will be enumerated and the deploy private key will be found, allowing the clone to proceed.
so I’m going to pop the public deployment key contents into ~/.ssh/authorized_keys
of the root account and then test to see if I can SSH into it using the private key specifically.
Nice, i’m in, but Can I clone??
Well, no you dummy, the private key is still needed. so copy that over too THEN see if you can clone
I’m pretty sure I understand why that worked. so lets try to implement it into the ansible playbook and test it out.
Testing the config
Friggin.
Glorious.
So a couple weird things at this point:
- First, my test VM became dirty and NOTHING would work. I reset the VM to it;s fresh install snapshot and low and behold the process i identified earlier worked
- Copying my SSH keys to root threw permissions (keys too permissive) errors but what was strange was using ansible’s builtin copy module to set the file permissions gave it some weeeeeird modes So i set the file permissions manually. (600,644,700)
- I for some reason needed to set the key_file argument of the builtin in git module and after that everything was gucci
Building and Deploying the research portal.
So, I’m not doing this the correct way. I believe that you would have a build server with a runner install to build the application and then that artifact would be posted somewhere for deployment. I’ll flesh this bone out another day, but for now I’m going to build the app after each milestone so I have a compiled release and then run my ansible playbook to deploy from the build dir.
(thisisgonnabeabitch)
A PIVOT YOU WOULD NOW BELIEVE OCCURS…
You may have seen in Devlog #003 I made the decision to move my projects and my home lab in general over to Ubuntu Server since, primarily, most of the software I want to use for this project support ubuntu and debian-based distros in the first place and that I don’t really need the slow releases and industrial security controls. So let’s go ahead and stand up an Ubuntu Server 22.04 Server on my mac and get to work….
Where Do we stand?
- Need to change the Package manager in my Ansible Deployment from dnf to apt
- Need to install firewall-cmd
- change group from nginx to www-data
- Change user in nginx config to web
- Change test index from the EL-based path to the Ubuntu-based path.
- Does NGINX actually use
/usr/share/nginx/html
as it’s web dir?- NEWP, it’s
/var/www/html
, so that has to change as well.- Touch Folder Create
- Touch Webroot definition in NGINX Config
- NEWP, it’s
This is why Ansible.
So In less than 20 minutes worth of work. I have successfully pivoted from Enterprise Linux to Ubuntu Linux. I am back where I started with my deployment so now all I gotta do is get my built app into the webroot and we can all this one a diddle.
OKAY NOW FOR THE DEPLOYMENT.
So part of my CI/CD pipline will DEPLOYING the built/available wab app in the repo’s build/web directory. So the step I need to perform for this are:
- name: CODE DEPLOY - CLONE THE CODE.
ansible.builtin.git:
repo: git@repos.lan:contegra-archive-operations/research-portal.git
key_file: /root/.ssh/DeploymentKeys
dest: /root/code
So in the snippet above I am using the prviate key of the DeploymentKeys pair that I configured in gitlab above to clone main into /root/code
so I can unpack it to NGINX
- name: CODE DEPLOY - COPY CODE FROM BUILD DIR TO WEB ROOT
ansible.builtin.shell:
cmd:cd /root/code/contegra_research_portal/build/web/ cp -R * /var/www/web/
Copy my compiled web app from the build dir of this release’s main repo and copy the compiled application into my web root.
Quick pitstop: it crossed my mind that my deployment lacks https. For now the task is to just get the deployment working, so I’ve created some tags and and an issue to address this in my backlog.
HOKAY. That’s a post!
You may also like
This site uses Akismet to reduce spam. Learn how your comment data is processed.
Archives
Calendar
M | T | W | T | F | S | S |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
Leave a Reply