---
title: Pingvin
description: Install Pingvin Share, a self-hosted file sharing platform to send files securely without relying on WeTransfer or Google Drive.
---


:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
# Pingvin

::note
🎯 __Objectives:__

- Install Pingvin
- Expose Pingvin
::

[Pingvin](https://github.com/stonith404/pingvin-share) is a tool for quickly sharing files, similar to WeTransfer. Its many sharing options (password, expiration time, custom link, etc.) make it the ideal tool for sharing files quickly. Pingvin can also create _upload requests_, i.e. a shareable link you can send to someone so they can upload their files for you to retrieve.

![picture](/img/serveex/pingvin.png)

## Installation
---
Open Dockge, click `compose`, name the stack `pingvin`, then copy-paste this:

```yaml
---
services:
  pingvin-share:
    container_name: pingvin
    image: stonith404/pingvin-share
    restart: unless-stopped
    ports:

      - 3600:3000
    volumes:

      - /docker/pingvin/data:/opt/app/backend/data
      - /docker/pingvin/data/img:/opt/app/frontend/public/img
      - /docker/pingvin/uploads:/opt/app/backend/uploads # path to the folder where you want to store files uploaded to pingvin. Change to your preference.
    depends_on:
      clamav:
        condition: service_healthy
    networks:

      - swag

  clamav: #antivirus for the files
    restart: unless-stopped
    image: clamav/clamav
```
::note

From here on, we assume the network name for Swag is `swag_default`.
::

::tip
✨ __Tip:__ Add the watchtower label to each container to automate updates.

    ```yaml
    services:
      pingvin-share:
        #...
        labels:

          - com.centurylinklabs.watchtower.enable=true
      
      clamav:
        #...
        labels:

          - com.centurylinklabs.watchtower.enable=true
    ```
::

Deploy the container and go to `http://yourserverip:3600`. That's it—your Pingvin web UI instance is up and running!

::caution

__If it fails:__ check your firewall rules.
::

## Exposing Pingvin with Swag
---
The whole point of a solution like this is being able to access it remotely, from all your devices. To do this, we'll expose Pingvin through Swag.

::note
📋 __Prerequisite:__ <br/><br/>
We assume you have the subdomain `pingvin.mydomain.com` with a `CNAME` pointing to `mydomain.com` in your [DNS zone](/general/networking/dns). And of course, [unless you're using Cloudflare Zero Trust](/serveex/security/cloudflare), port `443` on your router is forwarded to port `443` on your server via [NAT rules](/general/networking/nat).
::

In Dockge, go to the SWAG stack and edit the compose file to add the pingvin network:

```yaml
services:
  swag:
     container_name: # ...
      # ... 
     networks:             # Connects the container to the custom network 
      # ...           

      - pingvin            # Name of the network declared in the stack
    
networks:                  # Defines the custom network
  # ...
  pingvin:                 # Name of the network declared in the stack
    name: pingvin_default  # Actual name of the external network
    external: true         # States that it's a network to look up externally
```

::note

From here on, we assume the pingvin network name is `pingvin_default`. You can verify the connection is working by visiting the SWAG dashboard at http://yourserverip:81.
::

Redeploy the stack by clicking "deploy" and wait for SWAG to be fully up.

In the Swag folders, create the `pingvin.subdomain.conf` file.

::tip

__Tip:__ you can use [File Browser](/serveex/files/file-browser) to browse your files and edit your documents instead of using terminal commands.
::

```sh
sudo nano /docker/swag/config/nginx/proxy-confs/pingvin.subdomain.conf
```
Paste the configuration below:

```nginx
## Version 2023/12/19

server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name pingvin.*;

    include /config/nginx/ssl.conf;

    client_max_body_size 0;

    #if ($lan-ip = yes) { set $geo-whitelist yes; }
    #if ($geo-whitelist = no) { return 404; }
    if ($geo-blacklist = no) { return 404; }

    # enable for ldap auth (requires ldap-location.conf in the location block)
    #include /config/nginx/ldap-server.conf;

    # enable for Authelia (requires authelia-location.conf in the location block)
    #include /config/nginx/authelia-server.conf;

    # enable for Authentik (requires authentik-location.conf in the location block)
    #include /config/nginx/authentik-server.conf;

    location / {
        # enable the next two lines for http auth
        #auth_basic "Restricted";
        #auth_basic_user_file /config/nginx/.htpasswd;

        # enable for ldap auth (requires ldap-server.conf in the server block)
        #include /config/nginx/ldap-location.conf;

        # enable for Authelia (requires authelia-server.conf in the server block)
        #include /config/nginx/authelia-location.conf;

        # enable for Authentik (requires authentik-server.conf in the server block)
        #include /config/nginx/authentik-location.conf;

        include /config/nginx/proxy.conf;
        include /config/nginx/resolver.conf;
        set $upstream_app pingvin;
        set $upstream_port 3000;
        set $upstream_proto http;
        proxy_pass $upstream_proto://$upstream_app:$upstream_port;

    }
}

```

Press :kbd{value="Ctrl+O"}, then :kbd{value="Enter"} to save, and :kbd{value="Ctrl+X"} to exit.

That's it, you've exposed Pingvin!

## Securing Pingvin with Authentik

You can protect this app natively with Authentik by following the instructions below.

1. In your Authentik admin area, create an OAuth2/OpenID provider.

2. Fill in each section as follows, replacing `mydomain.com` with your own domain. Copy the `Client ID` and `Client Secret` fields somewhere safe.

![picture](/img/serveex/pingvin-auth1.png)
![picture](/img/serveex/pingvin-auth2.png)
![picture](/img/serveex/pingvin-auth3.png)

3. Save and create a `pingvin` application as follows.

![picture](/img/serveex/pingvin-auth4.png)

4. Save and go to your list of outposts. Add the pingvin provider to your outpost.

5. Leave Authentik, and go to Pingvin's admin interface.

6. In the _"OAuth"_ section, fill in the following fields:
- `OpenID discovery URI` with `https://pingvin.mydomain.com/application/o/pingvin/.well-known/openid-configuration` (don't forget to replace `mydomain.com` with your own domain)
- `OpenID username claim` with `preferred_username`
- `OpenID client ID` with the ID you copied in step 2.
- `OpenID client secret` with the token you copied in step 2.

That's it—from now on, when you log in to Pingvin, an "Open ID" button will be available below the login form.
