Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updating Manual Install Instructions Based on Feedback from slangerx #2328

Merged
merged 8 commits into from
Jul 17, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Alpaca & Crayfish updates
seth-shaw-asu committed Jul 8, 2024
commit e924239fcfa9b2b1d4ce8040ad4b4c637198123b
101 changes: 76 additions & 25 deletions docs/installation/manual/installing-alpaca.md
Original file line number Diff line number Diff line change
@@ -10,7 +10,9 @@

## Installing ActiveMQ

In our case, the default installation method for ActiveMQ via `apt-get` will suffice.
Some users have been able to install ActiveMQ from the standard package repositories. Others, however, have needed to install it manually.

### Option 1: System Provided Packages

```bash
sudo apt-get -y install activemq
@@ -32,15 +34,69 @@ sudo apt-cache policy activemq

Write down the version listed under `Installed: `.

### Option 2: Manual Install

Git the latest ActiveMQ 5.x version number from https://archive.apache.org/dist/activemq which will be put in place of `[ACTIVEMQ_VERSION_NUMBER]`.

```bash
cd /opt
sudo wget http://archive.apache.org/dist/activemq/[ACTIVEMQ_VERSION_NUMBER]/apache-activemq-[ACTIVEMQ_VERSION_NUMBER]-bin.tar.gz
sudo tar -xvzf apache-activemq-[ACTIVEMQ_VERSION_NUMBER]-bin.tar.gz
sudo mv apache-activemq-[ACTIVEMQ_VERSION_NUMBER] /opt/activemq
sudo addgroup --quiet --system activemq
sudo adduser --quiet --system --ingroup activemq --no-create-home --disabled-password activemq
sudo chown -R activemq:activemq /opt/activemq
sudo rm -R apache-activemq-[ACTIVEMQ_VERSION_NUMBER]-bin.tar.gz
```

Add ActiveMQ as a service:
`/etc/systemd/system/activemq.service | root:root/644
```
[Unit]
Description=Apache ActiveMQ
After=network.target
[Service]
Type=forking
User=activemq
Group=activemq
ExecStart=/opt/activemq/bin/activemq start
ExecStop=/opt/activemq/bin/activemq stop
[Install]
WantedBy=multi-user.target
```

Update the WebConsolePort host property settings in `/opt/activemq/conf/jetty.xml` from `<property name="host" value="127.0.0.1"/>` to `<property name="host" value="0.0.0.0"/>` so that you can access the dashboard from outside the local machine.

Optionally, change the dashboard user credentials in `/opt/activemq/conf/users.properties`.

*Note*
> Updating the web console port and user properties are potential security holes. It is best to restrict the host setting and create a more secure username/password combination for production.
Set the service to start on machine startup and start it up:
```bash
sudo systemctl daemon-reload
sudo systemctl start activemq
sudo systemctl enable activemq
sudo systemctl status activemq
sudo systemctl restart activemq
sudo apt-cache policy activemq # note version number
```

The service should now be available at `http://localhost:8161/`


## Installing Alpaca

Install Java 11+ if you haven't already.

Make a directory for Alpaca and download the latest version of Alpaca from the [Maven repository](https://repo1.maven.org/maven2/ca/islandora/alpaca/islandora-alpaca-app). E.g.
```
mkdir /opt/alpaca
sudo mkdir /opt/alpaca
cd /opt/alpaca
curl -L https://repo1.maven.org/maven2/ca/islandora/alpaca/islandora-alpaca-app/2.2.0/islandora-alpaca-app-2.2.0-all.jar -o alpaca.jar
sudo curl -L https://repo1.maven.org/maven2/ca/islandora/alpaca/islandora-alpaca-app/2.2.0/islandora-alpaca-app-2.2.0-all.jar -o alpaca.jar
```

### Configuration
@@ -55,7 +111,7 @@ The properties are:

```
# Common options
error.maxRedeliveries=4
error.maxRedeliveries=5
```
This defines how many times to retry a message before failing completely.

@@ -79,11 +135,6 @@ jms.connections=10
```
This defines the pool of connections to the ActiveMQ instance.

```
jms.concurrent-consumers=1
```
This defines how many messages to process simultaneously.

#### islandora-indexing-fcrepo

This service manages a Drupal node into a corresponding Fedora resource.
@@ -108,20 +159,20 @@ These define the various queues to listen on for the indexing/deletion
messages. The part after `queue:` should match your Islandora instance "Actions".

```
fcrepo.indexer.milliner.baseUrl=http://localhost:8000/milliner
fcrepo.indexer.milliner.baseUrl=http://localhost/milliner
```
This defines the location of your Milliner microservice.

```
fcrepo.indexer.concurrent-consumers=1
fcrepo.indexer.max-concurrent-consumers=1
fcrepo.indexer.concurrent-consumers=-1
fcrepo.indexer.max-concurrent-consumers=-1
```
These define the default number of concurrent consumers and maximum number of concurrent
consumers working off your ActiveMQ instance.
A value of `-1` means no setting is applied.

```
fcrepo.indexer.async-consumer=true
fcrepo.indexer.async-consumer=false
```

This property allows the concurrent consumers to process concurrently; otherwise, the consumers will wait to the previous message has been processed before executing.
@@ -134,7 +185,7 @@ It's properties are:

```
# Triplestore indexer options
triplestore.indexer.enabled=false
triplestore.indexer.enabled=true
```

This defines whether the Triplestore indexer is enabled or not.
@@ -154,8 +205,8 @@ triplestore.baseUrl=http://localhost:8080/bigdata/namespace/kb/sparql
This defines the location of your triplestore's SPARQL update endpoint.

```
triplestore.indexer.concurrent-consumers=1
triplestore.indexer.max-concurrent-consumers=1
triplestore.indexer.concurrent-consumers=-1
triplestore.indexer.max-concurrent-consumers=-1
```

These define the default number of concurrent consumers and maximum number of concurrent
@@ -164,7 +215,7 @@ A value of `-1` means no setting is applied.


```
triplestore.indexer.async-consumer=true
triplestore.indexer.async-consumer=false
```

This property allows the concurrent consumers to process concurrently; otherwise, the consumers will wait to the previous message has been processed before executing.
@@ -184,7 +235,7 @@ derivative.<item>.enabled=true
This defines if the `item` service is enabled.

```
derivative.<item>.in.stream=queue:islandora-item-connector.index
derivative.<item>.in.stream=queue:islandora-item-connector-<item>
```

This is the input queue for the derivative microservice.
@@ -197,8 +248,8 @@ derivative.<item>.service.url=http://example.org/derivative/convert
This is the microservice URL to process the request.

```
derivative.<item>.concurrent-consumers=1
derivative.<item>.max-concurrent-consumers=1
derivative.<item>.concurrent-consumers=-1
derivative.<item>.max-concurrent-consumers=-1
```

These define the default number of concurrent consumers and maximum number of concurrent
@@ -207,7 +258,7 @@ A value of `-1` means no setting is applied.


```
derivative.<item>.async-consumer=true
derivative.<item>.async-consumer=false
```

This property allows the concurrent consumers to process concurrently; otherwise, the consumers will wait to the previous message has been processed before executing.
@@ -219,14 +270,14 @@ derivative.systems.installed=houdini,fits
derivative.houdini.enabled=true
derivative.houdini.in.stream=queue:islandora-connector-houdini
derivative.houdini.service.url=http://127.0.0.1:8000/houdini/convert
derivative.houdini.service.url=http://127.0.0.1/houdini/convert
derivative.houdini.concurrent-consumers=1
derivative.houdini.max-concurrent-consumers=4
derivative.houdini.async-consumer=true
derivative.fits.enabled=true
derivative.fits.in.stream=queue:islandora-connector-fits
derivative.fits.service.url=http://127.0.0.1:8000/crayfits
derivative.fits.service.url=http://127.0.0.1/crayfits
derivative.fits.concurrent-consumers=2
derivative.fits.max-concurrent-consumers=2
derivative.fits.async-consumer=false
@@ -306,7 +357,7 @@ Description=Alpaca service
After=network.target
[Service]
Type=forking
Type=simple
ExecStart=java -jar /opt/alpaca/alpaca.jar -c /opt/alpaca/alpaca.properties
ExecStop=/bin/kill -15 $MAINPID
SuccessExitStatus=143
@@ -316,4 +367,4 @@ Restart=always
WantedBy=default.target
```

Now you can start the service by running `systemctl start alpaca` and set it to come up when the system reboots with `systemctl enable alpaca`.
Now you can start the service by running `sudo systemctl start alpaca` and set it to come up when the system reboots with `sudo systemctl enable alpaca`. Check the status by running `sudo systemctl status alpaca`.
246 changes: 121 additions & 125 deletions docs/installation/manual/installing-crayfish.md
Original file line number Diff line number Diff line change
@@ -4,9 +4,51 @@
The manual installation documentation is in need of attention. We are aware that some components no longer work as documented here. If you are interested in helping us improve the documentation, please see [Contributing](../../../contributing/CONTRIBUTING).

## In this section, we will install:
- [FITS Web Service](https://projects.iq.harvard.edu/fits), a webservice for identifying file metadata
- [Islandora/Crayfish](https://github.com/islandora/crayfish), the suite of microservices that power the backend of Islandora 2.0
- Indvidual microservices underneath Crayfish

## FITS Web Service

The FITS Web Service is used to extract file metadata from files. The Crayfish microservice CrayFits will use this service to push FITS metadata back to Drupal. It comes in two pieces, the actual FITS tool and the FITS Webservice which runs in Tomcat.

FITS itself wraps other file identification and metadata tools which may require installing additional libraries. On Ububtu 20.04, the version this guide is using, we will install a few:

```bash
sudo apt install mediainfo python3-jpylyzer
```

To set up the FITS application, first find the [latest FITS version on GitHub](https://github.com/harvard-lts/fits/releases) to replace the `[FITS_VERSION_NUMBER]` and then run the following commands:

```bash
cd /opt
sudo wget https://github.com/harvard-lts/fits/releases/download/[FITS_VERSION_NUMBER]/fits-[FITS_VERSION_NUMBER].zip
sudo unzip /opt/fits-[FITS_VERSION_NUMBER].zip -d /opt/fits
```

Similarly with the FITS webservice, [get the current service version number](https://github.com/harvard-lts/FITSservlet/releases) to replace `[FITS_SERVICE_WAR_VERSION_NUMBER]`:

Download the FITS webservice:

```bash
sudo -u tomcat wget -O /opt/tomcat/webapps/fits.war https://github.com/harvard-lts/FITSservlet/releases/download/[FITS_SERVICE_WAR_VERSION_NUMBER]/fits-service-[FITS_SERVICE_WAR_VERSION_NUMBER].war
```

Configure the webservice but adding the following lines to the bottom of `/opt/tomcat/conf/catalina.properties`:

```
fits.home=/opt/fits
shared.loader=/opt/fits/lib/*.jar
```

Restart Tomcat:

```
sudo systemctl restart tomcat
```

Wait for a few minutes to let the service start up the first time and then visit `http://localhost:8080/fits/` to ensure it is working. You can also follow the catalina logs to see how tomcat is progressing in setting up each service it is running: `sudo tail -f /opt/tomcat/logs/catalina.out`. To stop following the logs, hit control-C.

## Crayfish 2.0

### Installing Prerequisites
@@ -19,13 +61,12 @@ Some packages need to be installed before we can proceed with installing Crayfis
- Poppler, which will be used for generating PDFs

```bash
sudo apt-get install software-properties-common
sudo add-apt-repository -y ppa:lyrasis/imagemagick-jp2
sudo apt-get update
sudo apt-get -y install imagemagick tesseract-ocr ffmpeg poppler-utils
```

**NOTICE:** If you get the `sudo: apt-add-repository: command not found`, run `sudo apt-get install software-properties-common` in order to make the command available.

### Cloning and Installing Crayfish

We’re going to clone Crayfish to `/opt`, and individually run `composer install` against each of the microservice subdirectories.
@@ -39,6 +80,7 @@ sudo -u www-data composer install -d crayfish/Houdini
sudo -u www-data composer install -d crayfish/Hypercube
sudo -u www-data composer install -d crayfish/Milliner
sudo -u www-data composer install -d crayfish/Recast
sudo -u www-data composer install -d crayfish/CrayFits
```

### Preparing Logging
@@ -58,43 +100,27 @@ Each Crayfish component requires one or more `.yaml` file(s) to ensure everythin

The following configuration files represent somewhat sensible defaults; you should take consideration of the logging levels in use, as this can vary in desirability from installation to installation. Also note that in all cases, `http` URLs are being used, as this guide does not deal with setting up https support. In a production installation, this should not be the case. These files also assume a connection to a PostgreSQL database; use a `pdo_mysql` driver and the appropriate `3306` port if using MySQL.

*Note:*
> For Crayfish microservices use the `lexik_jwt_authentication` package. They are configured to use the `JWT_PUBLIC_KEY` environment variable to find the public key we created earlier (`/opt/keys/syn_public.key`). Later on in this guide we will add the environment variable to the Apache configs, but you may alternatively write the path to the key in the `lexik_jwt_authentication.yaml` file that resides along-side the `security.yaml` files we edit in this section.
#### Homarus (Audio/Video derivatives)

`/opt/crayfish/Homarus/cfg/config.yaml | www-data:www-data/644`
```yaml
---
homarus:
executable: ffmpeg
mime_types:
valid:
- video/mp4
- video/x-msvideo
- video/ogg
- audio/x-wav
- audio/mpeg
- audio/aac
- image/jpeg
- image/png
default: video/mp4
mime_to_format:
valid:
- video/mp4_mp4
- video/x-msvideo_avi
- video/ogg_ogg
- audio/x-wav_wav
- audio/mpeg_mp3
- audio/aac_m4a
- image/jpeg_image2pipe
- image/png_image2pipe
default: mp4
fedora_resource:
base_url: http://localhost:8080/fcrepo/rest
log:
level: NOTICE
file: /var/log/islandora/homarus.log
syn:
enable: true
config: /opt/fcrepo/config/syn-settings.xml
Enable JSON Web Token (JWT) based access to the service by updating the security settings. Edit `/opt/crayfish/Homarus/config/packages/security.yaml` to set firewalls: main: anonymous to `false` and uncomment the `provider` and `jwt` lines further down in that section.

Edit `/opt/crayfish/Homarus/config/packages/monolog.yaml` to point to the new logging directory:

```yml
homarus:
type: rotating_file
path: /var/logs/islandora/Homarus.log
```
Edit the commons config to update it with Fedora's location (if necessary) and enable the apix middleware in `/opt/crayfish/Homarus/config/packages/crayfish_commons.yaml`:

```yml
crayfish_commons:
fedora_base_uri: 'http://localhost:8080/fcrepo/rest'
apix_middleware_enabled: true
```

#### Houdini (Image derivatives)
@@ -108,7 +134,7 @@ Currently the Houdini microservice uses a different system (Symfony) than the ot
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
app.executable: /usr/local/bin/convert
app.executable: /usr/bin/convert
app.formats.valid:
- image/jpeg
- image/png
@@ -142,14 +168,15 @@ services:
# please note that last definitions always *replace* previous ones
```

`/opt/crayfish/Houdini/config/packages/crayfish_commons.yml | www-data:www-data/644`
`/opt/crayfish/Houdini/config/packages/crayfish_commons.yaml | www-data:www-data/644`
```yaml
crayfish_commons:
fedora_base_uri: 'http://localhost:8080/fcrepo/rest'
syn_config: '/opt/fcrepo/config/syn-settings.xml'
syn_config: /opt/fcrepo/config/syn-settings.xml
syn_enabled: True
```

`/opt/crayfish/Houdini/config/packages/monolog.yml | www-data:www-data/644`
`/opt/crayfish/Houdini/config/packages/monolog.yaml | www-data:www-data/644`
```yaml
monolog:
@@ -164,38 +191,38 @@ monolog:

The below files are two versions of the same file to enable or disable JWT token authentication.

`/opt/crayfish/Houdini/config/packages/security.yml | www-data:www-data/644`
`/opt/crayfish/Houdini/config/packages/security.yaml | www-data:www-data/644`

Enabled JWT token authentication:
```yaml
# To disable Syn checking, set syn_enabled=false in crayfish_commons.yaml and remove this configuration file.
security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
jwt_user_provider:
id: Islandora\Crayfish\Commons\Syn\JwtUserProvider
users_in_memory: { memory: null }
jwt:
lexik_jwt: ~
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
# To enable Syn, change anonymous to false and uncomment the lines further below
anonymous: false
# Need stateless or it reloads the User based on a token.
stateless: true
provider: jwt_user_provider
guard:
authenticators:
- Islandora\Crayfish\Commons\Syn\JwtAuthenticator
# To enable JWT authentication, uncomment the below 2 lines and change anonymous to false above.
provider: jwt
jwt: ~
# activate different ways to authenticate
# https://symfony.com/doc/current/security.html#firewalls-authentication
# https://symfony.com/doc/5.4/security.html#firewalls-authentication
# https://symfony.com/doc/current/security/impersonating_user.html
# https://symfony.com/doc/5.4/security/impersonating_user.html
# switch_user: true
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
@@ -224,74 +251,38 @@ security:

#### Hypercube (OCR)

`/opt/crayfish/Hypercube/cfg/config.yaml | www-data:www-data/644`
```yaml
---
hypercube:
tesseract_executable: tesseract
pdftotext_executable: pdftotext
fedora_resource:
base_url: http://localhost:8080/fcrepo/rest
log:
level: NOTICE
file: /var/log/islandora/hypercube.log
syn:
enable: true
config: /opt/fcrepo/config/syn-settings.xml
Enable JSON Web Token (JWT) based access to the service by updating the security settings. Edit `/opt/crayfish/Hypercube/config/packages/security.yaml` to set firewalls: main: anonymous to `false` and uncomment the `provider` and `jwt` lines further down in that section.

Edit `/opt/crayfish/Hypercube/config/packages/monolog.yaml` to point to the new logging directory:

```yml
hypercube:
type: rotating_file
path: /var/logs/islandora/Hypercube.log
```

Edit the commons config to update it with Fedora's location (if necessary) and enable the apix middleware in `/opt/crayfish/Hypercube/config/packages/crayfish_commons.yaml`:

```yml
crayfish_commons:
fedora_base_uri: 'http://localhost:8080/fcrepo/rest'
apix_middleware_enabled: true
```

#### Milliner (Fedora indexing)

`/opt/crayfish/Milliner/cfg/config.yaml | www-data:www-data/644`
```yaml
---
fedora_base_url: http://localhost:8080/fcrepo/rest
drupal_base_url: http://localhost
modified_date_predicate: http://schema.org/dateModified
strip_format_jsonld: true
debug: false
db.options:
driver: pdo_pgsql
host: 127.0.0.1
port: 5432
dbname: CRAYFISH_DB
user: CRAYFISH_DB_USER
password: CRAYFISH_DB_PASSWORD
log:
level: NOTICE
file: /var/log/islandora/milliner.log
syn:
enable: true
config: /opt/fcrepo/config/syn-settings.xml
```

#### Recast (Drupal to Fedora URI re-writing)

`/opt/crayfish/Recast/cfg/config.yaml | www-data:www-data/644`
```yaml
---
fedora_resource:
base_url: http://localhost:8080/fcrepo/rest
drupal_base_url: http://localhost
debug: false
log:
level: NOTICE
file: /var/log/islandora/recast.log
syn:
enable: true
config: /opt/fcrepo/config/syn-settings.xml
namespaces:
-
acl: "http://www.w3.org/ns/auth/acl#"
fedora: "http://fedora.info/definitions/v4/repository#"
ldp: "http://www.w3.org/ns/ldp#"
memento: "http://mementoweb.org/ns#"
pcdm: "http://pcdm.org/models#"
pcdmuse: "http://pcdm.org/use#"
webac: "http://fedora.info/definitions/v4/webac#"
vcard: "http://www.w3.org/2006/vcard/ns#"
Enable JSON Web Token (JWT) based access to the service by updating the security settings. Edit `/opt/crayfish/Milliner/config/packages/security.yaml` to set firewalls: main: anonymous to `false` and uncomment the `provider` and `jwt` lines further down in that section.

Edit `/opt/crayfish/Milliner/config/packages/monolog.yaml` to point to the new logging directory:

```yml
milliner:
type: rotating_file
path: /var/logs/islandora/Milliner.log
```

Edit the commons config to update it with Fedora's location (if necessary) and enable the apix middleware in `/opt/crayfish/Milliner/config/packages/crayfish_commons.yaml`:

Comment on lines +284 to +285

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

### Creating Apache Configurations for Crayfish Components

Finally, we need appropriate Apache configurations for Crayfish; these will allow other services to connect to Crayfish components via their HTTP endpoints.
@@ -304,11 +295,12 @@ These configurations would potentially have collisions with Drupal routes, if an

`/etc/apache2/conf-available/Homarus.conf | root:root/644`
```
Alias "/homarus" "/opt/crayfish/Homarus/src"
<Directory "/opt/crayfish/Homarus/src">
Alias "/homarus" "/opt/crayfish/Homarus/public"
<Directory "/opt/crayfish/Homarus/public">
FallbackResource /homarus/index.php
Require all granted
DirectoryIndex index.php
SetEnv JWT_PUBLIC_KEY /opt/keys/syn_public.key
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
</Directory>
```
@@ -320,39 +312,43 @@ Alias "/houdini" "/opt/crayfish/Houdini/public"
FallbackResource /houdini/index.php
Require all granted
DirectoryIndex index.php
SetEnv JWT_PUBLIC_KEY /opt/keys/syn_public.key
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
</Directory>
```
`/etc/apache2/conf-available/Hypercube.conf | root:root/644`
```
Alias "/hypercube" "/opt/crayfish/Hypercube/src"
<Directory "/opt/crayfish/Hypercube/src">
Alias "/hypercube" "/opt/crayfish/Hypercube/public"
<Directory "/opt/crayfish/Hypercube/public">
FallbackResource /hypercube/index.php
Require all granted
DirectoryIndex index.php
SetEnv JWT_PUBLIC_KEY /opt/keys/syn_public.key
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
</Directory>
```
`/etc/apache2/conf-available/Milliner.conf | root:root/644`
```
Alias "/milliner" "/opt/crayfish/Milliner/src"
<Directory "/opt/crayfish/Milliner/src">
Alias "/milliner" "/opt/crayfish/Milliner/public"
<Directory "/opt/crayfish/Milliner/public">
FallbackResource /milliner/index.php
Require all granted
DirectoryIndex index.php
SetEnv JWT_PUBLIC_KEY /opt/keys/syn_public.key
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
</Directory>
```
`/etc/apache2/conf-available/Recast.conf | root:root/644`
`/etc/apache2/conf-available/CrayFits.conf | root:root/644`
```
Alias "/recast" "/opt/crayfish/Recast/src"
<Directory "/opt/crayfish/Recast/src">
FallbackResource /recast/index.php
Alias "/crayfits" "/opt/crayfish/CrayFits/public"
<Directory "/opt/crayfish/CrayFits/public">
FallbackResource /crayfits/index.php
Require all granted
DirectoryIndex index.php
SetEnv JWT_PUBLIC_KEY /opt/keys/syn_public.key
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
</Directory>
```
@@ -362,7 +358,7 @@ Alias "/recast" "/opt/crayfish/Recast/src"
Enabling each of these configurations involves creating a symlink to them in the `conf-enabled` directory; the standardized method of doing this in Apache is with `a2enconf`.
```bash
sudo a2enconf Homarus Houdini Hypercube Milliner Recast
sudo a2enconf Homarus Houdini Hypercube Milliner CrayFits
```

### Restarting the Apache Service