Skip to content

Commit

Permalink
Add 'servidor' system user
Browse files Browse the repository at this point in the history
When running unattended (eg as a first-boot script on services like
DO/Vultr), Composer complains that both $HOME and $COMPOSER_HOME are
unset. While we could likely set the COMPOSER_HOME var to something
along the lines of /var/servidor/build/composer, we may as well have a
real system user with a home directory set to the install root.

This also updates all related commands to sudo via the servidor user,
and passes -H to sudo so that the home directory of servidor is used.
  • Loading branch information
dshoreman committed Aug 19, 2020
1 parent 162fc69 commit ceb733c
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 38 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0


## [Unreleased]
### Fixed
* Nginx sites no longer try to use the old PHP 7.3 socket


## [0.9.0] - 2020-08-11
Expand Down
6 changes: 5 additions & 1 deletion Vagrantfile
Expand Up @@ -13,7 +13,11 @@ Vagrant.configure("2") do |config|
disabled: true

config.vm.synced_folder ".", "/var/servidor",
create: true, owner: "www-data", group: "www-data",
create: true, owner: "998", group: "998",
mount_options: ["dmode=775,fmode=664"]

config.vm.synced_folder "./resources/test-skel", "/var/servidor/resources/test-skel",
create: false, owner: "www-data", group: "www-data",
mount_options: ["dmode=775,fmode=664"]

config.vm.synced_folder "./resources/test-skel/protected", "/var/servidor/resources/test-skel/protected",
Expand Down
51 changes: 35 additions & 16 deletions build/installer/_install.sh
Expand Up @@ -2,7 +2,7 @@ install_servidor() {
local app_url="http://servidor.local" branch="${1}"

info "Installing Servidor..."
clone_and_install
prepare_home && clone_and_install

info "Configuring application..."
configure_application && install_passport
Expand All @@ -13,34 +13,45 @@ install_servidor() {
finalise && print_success
}

prepare_home() {
log " Creating servidor system user..."
useradd -b /var -UG www-data -s /usr/sbin/nologin --system servidor
if ! is_vagrant; then
mkdir /var/servidor && chown servidor:servidor /var/servidor
fi

log "Adding www-data to the servidor group..."
usermod -aG servidor www-data
}

clone_and_install() {
cd /var/servidor || (err "Could not create system user!"; exit 1)
if ! is_vagrant; then
git clone -qb "${branch}" https://github.com/dshoreman/servidor.git /var/servidor
sudo -u servidor git clone -qb "${branch}" https://github.com/dshoreman/servidor.git .
fi
cd /var/servidor || (err "Could not clone Servidor!"; exit 1)

log "Installing required Composer packages..."
is_vagrant && cmd="sudo -Hu vagrant composer install" || cmd="composer install --no-dev"
${cmd} --no-interaction --no-progress --no-suggest
is_vagrant && c_dev="" || c_dev="--no-dev"
sudo -Hu servidor composer install ${c_dev} --no-interaction --no-progress --no-suggest

log "Compiling static assets..."
if is_vagrant; then
info " Running in Vagrant, skipping asset build!"
info " Run \`npm install && npm run dev\` to build for development."
else
npm_install && npm run prod
npm_install && sudo -Hu servidor npm run prod
fi
}

configure_application() {
[ -f .env ] || cp .env.example .env
[ -f .env ] || sudo -Hu servidor cp .env.example .env

log "Creating database..."
create_database

log "Generating secure app key..."
if grep -qP "^APP_KEY=$" .env; then
php artisan key:generate
sudo -Hu servidor php artisan key:generate
else
log " SKIPPED! A key has already been generated."
fi
Expand All @@ -49,13 +60,13 @@ configure_application() {
edit_line .env "APP_URL" "${app_url}"

log "Migrating the database..."
php artisan migrate --seed
sudo -Hu servidor php artisan migrate --seed
}

create_database() {
local password

password="$(tr -dc 'a-zA-Z0-9!@#$%^&*()_+=,-.<>/?;:|[]{}~' < /dev/urandom | head -c28)"
password="$(</dev/urandom tr -dc 'a-zA-Z0-9!@#$%^&*()_+=,-.<>/?;:|[]{}~' | head -c28)"

echo "DROP USER IF EXISTS 'servidor'@'localhost'; DROP DATABASE IF EXISTS servidor" | mysql && \
echo "CREATE USER 'servidor'@'localhost' IDENTIFIED BY '${password}'" | mysql && \
Expand All @@ -70,7 +81,7 @@ create_database() {
install_passport() {
local client

has_passport_keys || php artisan passport:keys
has_passport_keys || sudo -Hu servidor php artisan passport:keys

client="$(create_oauth_client)"
edit_line .env "PASSPORT_CLIENT_ID" "$(head -n1 <<< "${client}")"
Expand All @@ -83,11 +94,16 @@ patch_nginx() {
nginx_default_page > /var/www/html/index.nginx-debian.html

# NOTE: This should be much more restrictive before final release!
log " Setting permissions for servidor..."
echo "servidor ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/servidor && \
chmod 0440 /etc/sudoers.d/servidor

log " Setting permissions for www-data..."
echo "www-data ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/www-data
echo "www-data ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/www-data && \
chmod 0440 /etc/sudoers.d/www-data

log " Taking ownership of the Servidor storage dir..."
chown -R www-data:www-data /var/servidor/storage
chown -R servidor:www-data /var/servidor/storage

log "Setting owner to www-data on main web root..."
chown www-data:www-data /var/www
Expand All @@ -110,6 +126,9 @@ finalise() {
log "Copying basic shell aliases for vagrant user..."
vagrant_zshrc >> /home/vagrant/.zshrc && \
chown vagrant:vagrant /home/vagrant/.zshrc

log "Setting ownership on skeleton dir for tests..."
chown -R www-data:www-data /var/servidor/resources/test-skel
fi
}

Expand All @@ -119,9 +138,9 @@ ncurses_has_alacritty() {

npm_install() {
if npm_has_ci; then
npm ci
sudo -Hu servidor npm ci
else
rm -rf node_modules && npm install
sudo -Hu servidor rm -rf node_modules && sudo -Hu servidor npm install
fi
}

Expand All @@ -144,7 +163,7 @@ print_success() {
info
info "Servidor is listening at the following addresses:"
info " ${app_url}:8042/"
info " http://$(dig +short myip.opendns.com @resolver1.opendns.com):8042/"
info " http://$(dig -4 +short myip.opendns.com @resolver1.opendns.com):8042/"
info
is_vagrant && info "Don't forget to npm ci && npm run dev!" && info
echo
Expand Down
3 changes: 2 additions & 1 deletion build/installer/_passport.sh
Expand Up @@ -5,7 +5,8 @@ has_passport_keys() {
create_oauth_client() {
if [ "$(oauth_clients)" = "0" ]; then
log "Creating new oauth client..."
php artisan passport:client -n --password --name="Servidor API Client" | tail -n2 | cut -f3 -d' '
sudo -Hu servidor php artisan passport:client -n --password \
--name="Servidor API Client" | tail -n2 | cut -f3 -d' '
else
log "Fetching existing client..."

Expand Down
2 changes: 1 addition & 1 deletion resources/views/sites/server-templates/php.blade.php
Expand Up @@ -10,7 +10,7 @@
location ~ \.php$ {
try_files $uri =404;

fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

Expand Down
50 changes: 33 additions & 17 deletions setup.sh
Expand Up @@ -73,47 +73,56 @@ parse_opts() {
install_servidor() {
local app_url="http://servidor.local" branch="${1}"
info "Installing Servidor..."
clone_and_install
prepare_home && clone_and_install
info "Configuring application..."
configure_application && install_passport
log "Patching nginx config..."
patch_nginx && systemctl reload nginx.service
finalise && print_success
}
prepare_home() {
log " Creating servidor system user..."
useradd -b /var -UG www-data -s /usr/sbin/nologin --system servidor
if ! is_vagrant; then
mkdir /var/servidor && chown servidor:servidor /var/servidor
fi
log "Adding www-data to the servidor group..."
usermod -aG servidor www-data
}
clone_and_install() {
cd /var/servidor || (err "Could not create system user!"; exit 1)
if ! is_vagrant; then
git clone -qb "${branch}" https://github.com/dshoreman/servidor.git /var/servidor
sudo -u servidor git clone -qb "${branch}" https://github.com/dshoreman/servidor.git .
fi
cd /var/servidor || (err "Could not clone Servidor!"; exit 1)
log "Installing required Composer packages..."
is_vagrant && cmd="sudo -Hu vagrant composer install" || cmd="composer install --no-dev"
${cmd} --no-interaction --no-progress --no-suggest
is_vagrant && c_dev="" || c_dev="--no-dev"
sudo -Hu servidor composer install ${c_dev} --no-interaction --no-progress --no-suggest
log "Compiling static assets..."
if is_vagrant; then
info " Running in Vagrant, skipping asset build!"
info " Run \`npm install && npm run dev\` to build for development."
else
npm_install && npm run prod
npm_install && sudo -Hu servidor npm run prod
fi
}
configure_application() {
[ -f .env ] || cp .env.example .env
[ -f .env ] || sudo -Hu servidor cp .env.example .env
log "Creating database..."
create_database
log "Generating secure app key..."
if grep -qP "^APP_KEY=$" .env; then
php artisan key:generate
sudo -Hu servidor php artisan key:generate
else
log " SKIPPED! A key has already been generated."
fi
is_vagrant || app_url="http://$(hostname -f)"
edit_line .env "APP_URL" "${app_url}"
log "Migrating the database..."
php artisan migrate --seed
sudo -Hu servidor php artisan migrate --seed
}
create_database() {
local password
password="$(tr -dc 'a-zA-Z0-9!@#$%^&*()_+=,-.<>/?;:|[]{}~' < /dev/urandom | head -c28)"
password="$(</dev/urandom tr -dc 'a-zA-Z0-9!@#$%^&*()_+=,-.<>/?;:|[]{}~' | head -c28)"
echo "DROP USER IF EXISTS 'servidor'@'localhost'; DROP DATABASE IF EXISTS servidor" | mysql && \
echo "CREATE USER 'servidor'@'localhost' IDENTIFIED BY '${password}'" | mysql && \
echo "GRANT ALL PRIVILEGES ON *.* TO 'servidor'@'localhost'; FLUSH PRIVILEGES;" | mysql && \
Expand All @@ -123,7 +132,7 @@ create_database() {
}
install_passport() {
local client
has_passport_keys || php artisan passport:keys
has_passport_keys || sudo -Hu servidor php artisan passport:keys
client="$(create_oauth_client)"
edit_line .env "PASSPORT_CLIENT_ID" "$(head -n1 <<< "${client}")"
edit_line .env "PASSPORT_CLIENT_SECRET" "$(tail -n1 <<< "${client}")"
Expand All @@ -133,10 +142,14 @@ patch_nginx() {
log " Writing default index page..."
nginx_default_page > /var/www/html/index.nginx-debian.html
# NOTE: This should be much more restrictive before final release!
log " Setting permissions for servidor..."
echo "servidor ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/servidor && \
chmod 0440 /etc/sudoers.d/servidor
log " Setting permissions for www-data..."
echo "www-data ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/www-data
echo "www-data ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/www-data && \
chmod 0440 /etc/sudoers.d/www-data
log " Taking ownership of the Servidor storage dir..."
chown -R www-data:www-data /var/servidor/storage
chown -R servidor:www-data /var/servidor/storage
log "Setting owner to www-data on main web root..."
chown www-data:www-data /var/www
}
Expand All @@ -154,16 +167,18 @@ finalise() {
log "Copying basic shell aliases for vagrant user..."
vagrant_zshrc >> /home/vagrant/.zshrc && \
chown vagrant:vagrant /home/vagrant/.zshrc
log "Setting ownership on skeleton dir for tests..."
chown -R www-data:www-data /var/servidor/resources/test-skel
fi
}
ncurses_has_alacritty() {
infocmp alacritty > /dev/null 2>&1
}
npm_install() {
if npm_has_ci; then
npm ci
sudo -Hu servidor npm ci
else
rm -rf node_modules && npm install
sudo -Hu servidor rm -rf node_modules && sudo -Hu servidor npm install
fi
}
# The `ci` command was added in 5.7, but Ubuntu 18.04 ships 3.5.2.
Expand All @@ -182,7 +197,7 @@ print_success() {
info
info "Servidor is listening at the following addresses:"
info " ${app_url}:8042/"
info " http://$(dig +short myip.opendns.com @resolver1.opendns.com):8042/"
info " http://$(dig -4 +short myip.opendns.com @resolver1.opendns.com):8042/"
info
is_vagrant && info "Don't forget to npm ci && npm run dev!" && info
echo
Expand Down Expand Up @@ -272,7 +287,8 @@ has_passport_keys() {
create_oauth_client() {
if [ "$(oauth_clients)" = "0" ]; then
log "Creating new oauth client..."
php artisan passport:client -n --password --name="Servidor API Client" | tail -n2 | cut -f3 -d' '
sudo -Hu servidor php artisan passport:client -n --password \
--name="Servidor API Client" | tail -n2 | cut -f3 -d' '
else
log "Fetching existing client..."
local client_id
Expand Down
1 change: 0 additions & 1 deletion tests/Feature/Api/Files/CreatePathTest.php
Expand Up @@ -71,7 +71,6 @@ public function guest_cannot_create_a_folder(): void
/** @test */
public function authed_user_can_create_a_folder(): void
{
$this->withoutExceptionHandling();
$dir = resource_path('test-skel/newdir');

$response = $this->authed()->postJson($this->endpoint(), [
Expand Down
1 change: 0 additions & 1 deletion tests/Feature/Api/Sites/ViewSiteLogsTest.php
Expand Up @@ -15,7 +15,6 @@ class ViewSiteLogsTest extends TestCase
/** @test */
public function can_retrieve_content_for_site_log(): void
{
$this->withoutExceptionHandling();
$site = Site::create(['name' => 'logtest', 'type' => 'php']);

$response = $this->authed()->getJson('/api/sites/' . $site->id . '/logs/php');
Expand Down

0 comments on commit ceb733c

Please sign in to comment.