Manjaro server packages

I have been thinking of writing meta packages to automate setting up a simple lamp or lemp stack on manjaro. Now that manjaro-arm might be rising again ([POLL] Manjaro-ARM ressurrection?), I figured it might be time to get started. The idea would be to pull all the necessary packages as dependencies, and then call a install script after transaction to edit files and enable services.

Something like this:

# Maintainer: Chrysostomus

pkgdesc="A metapackage to setup a simple lemp stack"

package() {
	cd "$pkgname"
        install -Dm755 "lemp-setup" "$pkgdir/usr/bin/lemp-setup"
	install	-Dm755 "lemp.hook" "/usr/share/libalpm/hooks/lemp.hook"
	install	-Dm755 "nginx.conf" "/usr/share/lemp/nginx.conf"


Script to install lemp, lemp-setup:

# initialize database
sudo mysql_install_db --user=mysql --basedir=/usr --datadir=/var/lib/mysql
## Create php testpage
echo -n '<?php
?>' > /usr/share/nginx/html/test.php

## use the edited /etc/nginx/nginx.conf
cp /usr/share/lemp/nginx.conf /etc/nginx/nginx.conf
# enable php extensions 
sed -i '/ s/^;//' /etc/php/php.ini
sed -i '/ s/^;//' /etc/php/php.ini
# enable and start services
systemctl enable nginx mysqld php-fpm
systemctl start nginx mysqld php-fpm

# Give info 
echo "Your public IP is $(curl"

Hook to call the install script, lemp.hook:

Type = Package
Operation = Install
Target = lemp-manjaro

Description = Setting up LEMP stack
When = PostTransaction
Exec = /usr/bin/lemp-setup

Not sure if this would really work, because it calls an interactive script (mysql_secure_installation) in the post operation hook. Of course the package does not build yet, because the git repo does not yet exist. Also, I don' t know if the hook that package just installed gets triggered.

I made something similar for lamp stack too. I was thinking of making a package for nextcloud too, which would depend on manjaro-server. However, that one requires so many interactive parts that I think it is not feasible.

What do you guys think? Is this a good approach to this? Does it make sense?

I wonder if this can be done with a sort of lemp-settings package, using backup=() and a doing operations with a post-install file instead of calling scripts

1 Like

This kind of setup script can possibly be better served by use of an Ansible playbook (or other configuration management/deployment software). This would mean it's version-independent, and most of the issues and edge-cases you'd face have already been dealt with (e.g. what happens if someone re-installs the package or re-runs the setup script?).

Now - packaging an Ansible playbook to do this setup - that's worth looking into.

1 Like

Ansible seems good, but I'm a bit out of my depth here.

So, move old configuration files away and replace with new ones? That could make sense, and might manage uninstallation better. Good idea.

@Strit, could the manjaro-arm benefit from something like this?

Don't know much about Ansible, but from a quick look at their website, it looks to be a form of CI.
Manjaro-ARM used Jenkins CI before, which is quite easy to set up and can run shell commands on the machine it's running on.

Nope, Ansible is configuration management software.

I highly recommend you look into this instead of creating your own custom management scripts. This is a "solved problem": Ansible, Chef, Puppet, Salt Stack; take your pick.

If we're doing CI-based builds then buildbot is going to be worth a look.

Buildbot look interestingh. Kind of like Jenkins, just in python instead of java.
Will look into that a bit more.

Regarding Ansible and "configuration management software" I have no idea what that means or does. I barely grasp what Jenkins does. So what does Ansible do, that Jenkins does not?

Configuration management software is there to make system administration easier and repeatable, whether this is making sure system configuration remains in a "known state" or by making deployments and changes more reliable.

As an example, here's an Ansible playbook I wrote last week to deploy Discourse to Ubuntu 16.04+ systems:

- hosts: all
  remote_user: jonathon
  become: yes
  become_method: sudo
  - name: Perform apt update and upgrade
        upgrade: yes
        update_cache: yes
        cache_valid_time: 3600

  # Docker
  - name: Ensure old versions removed
        name: "{{ item }}"
        state: absent   
        purge: yes
        - docker
        - docker-engine
  - name: Docker prerequisites
        name: "{{ item }}"
        state: latest
        - apt-transport-https
        - ca-certificates
        - curl
        - git
        - unattended-upgrades
  - name: Docker package key
        id: 9DC858229FC7DD38854AE2D88D81803C0EBFCD88
        state: present
  - name: Docker repository
        repo: "deb [arch=amd64] {{ ansible_distribution_release }} stable"
        state: present
        filename: docker
        update_cache: yes
  - name: Install Docker
        name: docker-ce
        state: latest
        update_cache: yes
        cache_valid_time: 3600
  - name: Docker service
        name: docker
        enabled: yes
        state: started

  # System tweaks
  - name: Enable unattended-upgrades
    command: dpkg-reconfigure -plow unattended-upgrades
  - name: Disable transparent_hugepages for session
    command: 'echo never > /sys/kernel/mm/transparent_hugepage/enabled'
  - name: Disable transparent_hugepages at kernel level
        path: /etc/default/grub
        regexp: 'GRUB_CMDLINE_LINUX' 
        line: 'GRUB_CMDLINE_LINUX="transparent_hugepage=never"'
  - name: Rebuild GRUB
    command: update-grub
  - name: Set vm.overcommit_memory to 1
        name: vm.overcommit_memory
        value: 1   

  # Discourse
  - name: Discourse launcher directory
        path: /var/discourse
        state: directory
        mode: 0700
  - name: Clone Discourse launcher repo
        dest: /var/discourse 
        depth: 1
  - name: Insert app.yml
        src: app.yml
        dest: /var/discourse/containers/app.yml
        owner: root
        group: root
        mode: 0600
        path: /var/discourse/containers/app.yml
        regexp: '^  DISCOURSE_HOSTNAME:'
        line: "  DISCOURSE_HOSTNAME: {{ inventory_hostname }}"
  - name: Build/rebuild container
    command: /var/discourse/launcher rebuild app

  # Cleanup
  - name: Docker system prune
    command: docker system prune -f

I could have gone through a list of commands and typed them in, or scripted it in shell, but every time I run this playbook Ansible only applies changes that are necessary and the whole thing is a metric tonne more reliable than a shell script (which I have used for other deployments in the past).

It has a load of modules that will take care of the majority of requirements, like creating MySQL databases, enabling Apache modules, ... etc.

Continuous Integration, on the other hand, takes instructions and executes them every time a change is made. Normally this is used to take source code and compile and test it with every change so that any issues introduced can be narrowed down to an precise commit, which also means you don't ship a broken product.

For package building, this would mean taking PKGBUILD sources from a repo and building them whenever the source changes - i.e. automated builds.


I'm thinking of mainly as a learning project, because I'm trying to transition to some IT job. Ansible and to lesser extent puppet seem to be popular with employers for the types of jobs I could apply for, so learning them instead would make sense also from that point of view.

I'll look into this.

Forum kindly sponsored by