# Technical Docs for the Web Asset Server (Attachment Server)

**URL:** <https://speciforum.org/t/technical-docs-for-the-web-asset-server-attachment-server/657>\
**Category:** Technical Docs\
**Tags:** Specify-7, Specify-6, Members-only\
**Created:** [September 7, 2022, 5:25pm UTC](https://speciforum.org/t/technical-docs-for-the-web-asset-server-attachment-server/657 "2022-09-07T17:25:34Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Grant](https://yyz1.discourse-cdn.com/flex029/user_avatar/speciforum.org/grant/32/4255_2.png) [@Grant](https://speciforum.org/u/Grant)\
**Post date:** [September 7, 2022, 5:25pm UTC](https://speciforum.org/t/technical-docs-for-the-web-asset-server-attachment-server/657/1 "2022-09-07T17:25:34Z")

</div>

> 📖 This guide explains the technical documentation for the Web Asset Server and provides instructions for installation.

> [!help] Looking for user documentation?  
> See our article on the [Specify Web Asset Server (Attachment Server)](https://speciforum.org/t/specify-attachment-server-asset-server/715) here!

* * *

> [!Note]  
> The most recent edition of this is available on our GitHub under the web-asset-server project. [You can view this here](https://github.com/specify/web-asset-server/blob/master/README.md).

* * *

This is a sample attachment server implementation for Specify. This implementation is targetted at Ubuntu flavors, but will work with minor modifications on other Linux systems. It is not expected to work without extensive adaptation on Windows systems.  
We recommend limiting individual file size to 10mb, because Specify cannot efficiently create thumbnails for display, or display the full images.  
Large attachments (over 10MB) will negatively impact application performance because the browser must load the entire file into memory.

Specify users often manage originals on local servers identified by a catalog number or another identifier, retrieving them as needed. Many host full-resolution originals on a Digital Asset Management (DAM) service and include links to this service in Specify.

To learn about how the current Web Asset Server (WAS) is implemented and to learn more about how to integrate with a DAM, see here:

> [@Integrating a Custom DAM System with Specify](https://speciforum.org/t/integrating-a-custom-dam-system-with-specify/3642):
>
> gear This guide is for technical and IT users who want to integrate an existing or developing Digital Asset Management (DAM) system with Specify. If your institution uses a custom Digital Asset Management (DAM) system and you want Specify to connect to it directly, you can do this by having your DAM act like the default Web Asset Server (WAS). Some institutions choose to manage a drive of high-quality originals detached from the Specify instance, while others seek to use the same DAM betwe…

The Specify Collections Consortium is funded by its member  
institutions. The Consortium web site is: [http://www.specifysoftware.org](http://www.specifysoftware.org).

# Installation

## Docker

Docker in the preferred installation method for Web Asset Server.

Example `docker-compose.yml` is provided:

```yaml
version: '3.7'
services:

  asset-server:
    restart: unless-stopped
    image: specifyconsortium/specify-asset-service
    init: true
    volumes:
      # Store all attachments outside the container, in a separate
      # volume
      - "attachments:/home/specify/attachments"
    environment:
      # Replace this with the URL at which asset server would be
      # publicly available
      - SERVER_NAME=host.docker.internal
      - SERVER_PORT=80
      - ATTACHMENT_KEY=your asset server access key
      - DEBUG_MODE=false

volumes:
  attachments: # the asset-servers attachment files

```

## Installing system dependencies

The dependencies are:

1. _Python_ 3.12 is known to work.
2. _ExifRead_ for EXIF metadata.
3. _sh_ the Python shell command utility.
4. _bottlepy_ the Python web micro-framework.
5. _ImageMagick_ for thumbnailing.
6. _Ghostscript_ for PDF thumbnailing.
7. _Paste_ Python web server.

To install dependencies  
the following commands work on Ubuntu:

```shell
sudo apt-get -y install --no-install-recommends \
  python-pip \
  imagemagick \
  ghostscript
sudo pip install -r requirements.txt

```

## Cloning Web Asset Server source repository

Clone this repository.

```shell
git clone git://github.com/specify/web-asset-server.git

```

## Deployment

Adjust the settings in the `settings.py` in your working directory. Then  
run the server with the following command:

```shell
python server.py

```

In my experience, it has been easiest to deploy using the Python _Paste_ server.

In `settings.py` set the value `SERVER = 'paste'`.

To run the server on a privileged port, e.g. 80, the utility  
[authbind](http://en.wikipedia.org/wiki/Authbind) is recommended.

```shell
sudo apt-get install authbind

```

Assuming you are logged in as the user that will be used to run the server process,  
the following commands will tell _authbind_ to allow port 80 to be used:

```shell
touch 80
chmod u+x 80
sudo mv 80 /etc/authbind/byport

```

An _upstart_ script or _systemd_ unit file can be created to make sure the web asset server is started automatically.

It is important that the working directory is set to the path containing `server.py`  
so that _bottle.py_ can find the template files. See [“TEMPLATE NOT FOUND” IN MOD\_WSGI/MOD\_PYTHON](http://bottlepy.org/docs/dev/faq.html#template-not-found-in-mod-wsgi-mod-python).

Note: Some users have reported that `authbind` must be provided with the `--deep` option.  
If the asset server is failing to start due to permission problems, this may be a solution.

### Upstart

Create the file `/etc/init/web-asset-server.conf` with the following  
contents, adjusting the `setuid` user and directories as appropriate:

```auto
description "Specify Web Asset Server"
author "Ben Anhalt <anhalt@ku.edu>"

start on runlevel [234]
stop on runlevel [0156]

setuid anhalt

chdir /home/anhalt/web-asset-server
exec /usr/bin/authbind /usr/bin/python /home/anhalt/web-asset-server/server.py
respawn

```

Then reload the init config files and start the server:

```shell
sudo initctl reload-configuration
sudo start web-asset-server

```

By default, the server’s logs go to standard output which _upstart_ will redirect  
to `/var/log/upstart/web-asset-server.log`

### Systemd

Create the file `/etc/systemd/system/web-asset-server.conf` with the following  
contents, adjusting the usernames and paths as appropriate:

```conf
[Unit]
Description=Specify Web Asset Server
Wants=network.target

[Service]
User=specify
WorkingDirectory=/home/specify/web-asset-server
ExecStart=/usr/bin/authbind /usr/bin/python /home/specify/web-asset-server/server.py

```

Tell Systemd to reload its config with

```shell
sudo systemctl daemon-reload

```

# HTTPS

The easiest way to add HTTPS support, which is necessary to use the asset server with a Specify 7 server that is using HTTPS, is to place the asset server behind a reverse proxy such as Nginx. This also makes it possible to forego _authbind_ and run the asset server on an unprivileged port. The proxy must be configured to rewrite the `web_asset_store.xml` resource to adjust the links therein. An example configuration can be found in [this gist](https://gist.github.com/benanhalt/d43a3fa7bf04edfc0bcdc11c612b2278).

# Specify 6 Settings

You will generally want to add the asset server settings to the global Specify preferences so that all of the Specify clients obtain the same configuration.

The easiest way to do this is to open the database in Specify and navigate to the _About_ option in the help menu.

 ![About Specify](https://canada1.discourse-cdn.com/flex029/uploads/specifysoftware/original/2X/3/3f58fb9e1b2fc9ee0247b1c61bf7e9dafb406af5.jpeg)

In the resulting dialog double-click on the division name under _System Information_ on the right hand side. This will open a properties editor for the global preferences.

You will need to set four properties to configure access to the asset server:

- `USE_GLOBAL_PREFS` - `true`
- `attachment.key` – `##`
  - Replace `##` with the key from the following location:
    - obtain from asset server `settings.py` file if you have a local installation of 7
    - obtain from `docker-compose.yml` file if you use a Docker deployment

- `attachment.url``http://[YOUR_SERVER]/web_asset_store.xml`
- `attachment.use_path` `false`

If these properties do not already exist, they can be added using the Add Property button.

# Specify 7 Settings

If you are using the [Docker deployment method](https://speciforum.org/t/specify-7-installation-instructions/755#docker-compositions-2), you need to make sure that the `attachment.key` and `attachment.url` match the configuration in Specify 6.

For both the `specify7` and `specify7-worker` sections, you need to make sure that:

- `attachment.key` = `ASSET_SERVER_KEY`
- `attachment.url` = `ASSET_SERVER_URL`

```yml
  specify7:
    restart: unless-stopped
    image: specifyconsortium/specify7-service:v7
    init: true
    volumes:
      - "specify6:/opt/Specify:ro"
      - "static-files:/volumes/static-files"
    environment:
      - DATABASE_HOST=mariadb
      - DATABASE_PORT=3306
      - DATABASE_NAME=specify
      - MASTER_NAME=master
      - MASTER_PASSWORD=master
      - SECRET_KEY=change this to some unique random string
      - ASSET_SERVER_URL=http://host.docker.internal/web_asset_store.xml
      - ASSET_SERVER_KEY=your asset server access key
      - REPORT_RUNNER_HOST=report-runner
      - REPORT_RUNNER_PORT=8080
      - CELERY_BROKER_URL=redis://redis/0
      - CELERY_RESULT_BACKEND=redis://redis/1
      - LOG_LEVEL=WARNING
      - SP7_DEBUG=false

```

If you are using a local installation, in the `settings.py` file, you need to make sure that:

- `attachment.key` = `WEB_ATTACHMENT_KEY`
- `attachment.url` = `WEB_ATTACHMENT_URL`

> <https://github.com/specify/specify7/blob/0345888388ccf2d0366c96117b3c58469e770b80/specifyweb/settings/specify_settings.py#L26-L30>

# Compatibility with older versions of Python

- [Web Asset server for Python 2.7](https://github.com/specify/web-asset-server)
- [Python 2.6 compatibility](https://github.com/specify/web-asset-server#python-2.6-compatibility)

* * *

### Related: How does it work with Specify?

> [@How does Specify 7 work with the Web Asset Server?](https://speciforum.org/t/how-does-specify-7-work-with-the-web-asset-server/2817):
>
> book This article describes how attachments in Specify are linked to attachments on the [Web Asset Server](https://speciforum.org/t/specify-attachment-server-asset-server/715). Linking an Attachment to the Source When an attachment is uploaded to Specify, it is added to the database as a set of attachment records (in the attachment table and the joining attachment table, in this case collectionobjectattachment). In this example, I uploaded an attachment for a Collection Object with the catalog number 29499: Cita…

---

<div class="post-metadata">

**Author:** ![fedoras](https://yyz1.discourse-cdn.com/flex029/user_avatar/speciforum.org/fedoras/32/455_2.png) [@fedoras](https://speciforum.org/u/fedoras)\
**Post date:** [September 30, 2022, 12:19pm UTC](https://speciforum.org/t/technical-docs-for-the-web-asset-server-attachment-server/657/2 "2022-09-30T12:19:17Z")

</div>

Upon upload/import, does the web asset server read EXIF metadata and stores this information?

---

<div class="post-metadata">

**Author:** ![Grant](https://yyz1.discourse-cdn.com/flex029/user_avatar/speciforum.org/grant/32/4255_2.png) [@Grant](https://speciforum.org/u/Grant)\
**Post date:** [April 4, 2023, 2:26pm UTC](https://speciforum.org/t/technical-docs-for-the-web-asset-server-attachment-server/657/3 "2023-04-04T14:26:51Z")

</div>

Hi @fedoras,

Upon upload, the web asset server stores the file with EXIF metadata but doesn’t do anything with it. This EXIF metadata is stored with the image and can be viewed when the attachment is downloaded.
