# Technical Documentation: exposedev/expose

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/exposedev/expose)

### Overview (README.md)

[](https://expose.dev/?ref=github)

# Expose

[](https://packagist.org/packages/beyondcode/expose)
[](https://scrutinizer-ci.com/g/beyondcode/expose)
[](https://packagist.org/packages/beyondcode/expose)

An open-source ngrok alternative - written in PHP.

## ⭐️ Managed Expose & Expose Pro ⭐️

You can use a managed version with our proprietary platform and our free (EU) test server at the [official website](https://expose.dev). Upgrade to Expose Pro to use our global server network with your own custom domains and get high-speed tunnels all over the world.

[Create an account](https://expose.dev)

## Documentation

For installation instructions of your own server, in-depth usage and deployment details, please take a look at the [official documentation](https://expose.dev/docs).

### Security

If you discover any security related issues, please email marcel@beyondco.de instead of using the issue tracker.

## Credits

- [Marcel Pociot](https://github.com/mpociot)
- [All Contributors](../../contributors)

## License

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

---

### Introduction (`docs/introduction.md`)

---
title: Introduction
order: 1
---

# Introduction

Expose is a tunnel application that allows you to share your local sites and applications with others on the internet. It is open source, written in PHP and the best alternative to ngrok for PHP developers.

The easiest way to get started with Expose, is by creating a [free Expose token](https://expose.dev/register) and use our managed Expose server infrastructure, allowing you to register custom white-label domains, use custom subdomains, and invite additional team-members. The managed Expose network has a free plan that runs on the infrastructure in our data center in Germany – and a Pro plan that uses the global Expose network with access points all over the world.

If you decide to host your own Expose server, you can extend Expose with additional features and middleware classes on the server and client side. This gives your the full flexibility of true customization but comes with maintenance and hosting overhead.

Expose has a powerful CLI and a web-based dashboard. Both show you incoming HTTP requests on the client.

If you work with PHP, [install Expose now](/docs/getting-started/installation).

---

### Upgrade From V1 (`docs/upgrade-from-v1.md`)

---
title: Upgrade from Expose v1 
order: 2
---

# Upgrade Guide

Expose 2 is now available and comes with a lot of new features and improvements! We worked very hard to make the transition from Expose 1.x to 2.x as smooth as possible.

The easiest way to update your existing Expose 1 installation to Expose 2, is by using composer.

```bash
composer global require beyondcode/expose:2.0
```

This will download and install the latest version of Expose. Your existing authentication token and configuration file will still be valid after updating to the latest version.

**Important:** Even though the Expose 1.x client is backwards compatible with the new Expose servers, please upgrade to the latest client as soon as possible, as we will fade out support for the Expose 1.x client in the future.

## Upgrading to Expose ::pro

Some Expose features are not available on our free server and require self-hosting or a Pro plan. These features include custom subdomains, or the newly added sharing of TCP ports. 

If you want to upgrade your existing setup to Expose Pro, please [create a new Expose account](/register) and you get a new authentication token that can upgrade to Expose Pro.

---

### Api Authorization (`docs/api/authorization.md`)

---
title: Authorization
order: 1
---

# Authorization

The Expose server API uses the same authentication method as the expose admin interface itself.  
So you can use any of the configured user/password combinations as basic authentication.

---

### Api Settings (`docs/api/settings.md`)

---
title: Settings
order: 2
---

# Settings

Expose provides two API endpoints that allow you to either read or update the currently active server settings.

## Reading the settings

To retrieve the currently active configuration, you can perform a GET request to the `/api/settings` endpoint:

The result looks like this:

```json
{
   "configuration":{
      "hostname": "sharedwithexpose.com",
      "port": 8080,
      "database": "/home/forge/expose/database/expose.db",
      "validate_auth_tokens": false,
      "maximum_connection_length": 0,
      "subdomain": "expose",
      "subdomain_generator": "App\\Server\\SubdomainGenerator\\RandomSubdomainGenerator",
      "users": {
         "username":"password"
      },
      "user_repository": "App\\Server\\UserRepository\\DatabaseUserRepository",
      "messages": {
         "message_of_the_day":"Thank you for using expose.",
         "invalid_auth_token":"Authentication failed. Please check your authentication token and try again.",
         "subdomain_taken":"The chosen subdomain :subdomain is already taken. Please choose a different subdomain."
      }
   }
}
```

## Updating the settings

To update the currently active settings, send a POST request to the `/api/settings` endpoint.

The endpoint expects you to send the following data:

```
validate_auth_tokens: BOOLEAN

maximum_connection_length: INTEGER

messages: ARRAY
messages.message_of_the_day: STRING
messages.invalid_auth_token: STRING
messages.subdomain_taken: STRING
```

You will receive a response containing the updated configuration as JSON.

---

### Api Sites (`docs/api/sites.md`)

---
title: Sites
order: 3
---

# Sites

Expose provides two API endpoints that allow you to either retrieve all currently shared sites, or disconnect a site with a given site ID.

## Retrieving all shared sites

To retrieve the currently shared sites, you can perform a GET request to the `/api/sites` endpoint:

The result looks like this:

```json
{
   "sites":[
      {
         "id":10,
         "host":"beyondco.de.test",
         "client_id":"5ed94b485e2f6",
         "subdomain":"beyondcode",
         "shared_at":"2020-06-04 19:28:08"
      }
   ]
}
```

## Disconnecting a shared site

To disconnect a shared site from your server, you can perform a DELETE request to the `/api/sites/{site_id}` endpoint.

---

### Api Users (`docs/api/users.md`)

---
title: Users
order: 4
---

# Users

Expose provides three API endpoints that allow you to either retrieve all registered users, create a new user, or delete an existing user from the expose server.

## Retrieving all users

To retrieve the users, you can perform a GET request to the `/api/users` endpoint:

The result looks like this:

```json
{
   "users":[
	  {
		 "id":9,
		 "name":"miguel",
		 "auth_token":"858fad3d-2163-4af6-8c8d-68e89f80cf8c",
		 "created_at":"2020-06-04 19:31:26",
		 "updated_at":null
	  },
	  {
		 "id":8,
		 "name":"sebastian",
		 "auth_token":"360461ea-23b9-422e-bc76-7ca1b2ec8a91",
		 "created_at":"2020-06-04 19:31:17",
		 "updated_at":null
	  },
	  {
		 "id":7,
		 "name":"marcel",
		 "auth_token":"b5f3ee57-1e77-4a94-8b7f-da13e3dc6478",
		 "created_at":"2020-06-04 19:31:16",
		 "updated_at":null
	  }
   ]
}
```

## Creating a new user

To create a new user on the expose server, you can perform a POST request to the `/api/users` endpoint.

The endpoint expects you to send the following data:

```json
name: STRING
```

This will return a response containing the generated user:

```json
{
	"user": {
		"id":8,
		"name":"sebastian",
		"auth_token":"360461ea-23b9-422e-bc76-7ca1b2ec8a91",
		"created_at":"2020-06-04 19:31:17",
		"updated_at":null
	}
}
```

## Deleting a user

To delete a user on the expose server, you can perform a DELETE request to the `/api/users/{user_id}` endpoint.

> **Note:** The user's currently active shared sites will not be disconnected automatically.

---

### Client Basic Authentication (`docs/client/basic-authentication.md`)

---
title: Basic Authentication
order: 4
---

# Sharing sites with basic authentication

Expose allows you to share your local sites with custom basic authentication credentials.

This is useful, if you have a static subdomain that you share with someone else, for example a client, and you want to provide some additional security to it. Before someone can access your shared site, they need to provide the correct credentials.

> **Warning**: You can not add basic authentication to a website that already uses basic authentication.

To share your site with basic authentication, use:

```bash
expose --auth="admin:secret"
```

Or if you want to use the explicit sharing:

```bash
expose share my-site.test --auth="admin:secret"
```

This will share the local URL my-site.test with the username "admin" and the password "secret".

You can also use the basic authentication parameter in addition to a custom subdomain:

```bash
expose share my-site.test --subdomain=site --auth="admin:secret"
```

---

### Client Configuration (`docs/client/configuration.md`)

---
title: Configuration
order: 6
---

# Configuration

To configure the Expose client, you first need to publish the configuration file.

This can be done using the publish command:

```bash
expose publish
```

The configuration file will be written to your home directory inside a `.expose` folder:

`~/.expose/config.php`

You can also provide a custom location of the config file by providing the full path as a server variable.

```bash
EXPOSE_CONFIG_FILE="~/my-custom-config.php" expose share
```

And the default content of the configuration file is this:

```
/* Detailed source-code truncated for AI context efficiency. */
```

---

### Client Dashboard (`docs/client/dashboard.md`)

---
title: Local Dashboard
order: 2
---

# Dashboard

Once you share a local site, Expose shows you all incoming HTTP requests along with their status code and duration in your terminal:



While this is great to get a quick look of the incoming requests, you often need more information than this.

Because of that, Expose is also exposing a web based dashboard on port 4040.

Once you start sharing a site, Expose shows you a QR code that you can scan with your mobile device, to easily browse your shared sites on your phone or tablet.



When a request comes in, you can see all incoming HTTP requests as they hit your local site in realtime.
You can click on a specific request and see detailed information about the request and response. Expose provides several tools for developers to make webhook testing easier – the most powerful one is that you can replay requests without firing the webhook again. So if your previous process required to create multiple test orders to see how the paylods of your payment provider look like, Expose makes this a breeze by allowing you to replay these requests without creating more orders.

---

### Client Global Server Infrastructure (`docs/client/global-server-infrastructure.md`)

---
title: Global Server Infrastructure
order: 4
---

# Global Server Infrastructure ::pro

[Expose Pro](/get-pro) allows you to choose between multiple Expose servers around the world, so that you can use an endpoint closest to you.

To get a list of all the available Expose servers, you can run `expose servers`

```
$ expose servers

+------+---------------------------+------+
| Key  | Region                    | Type |
+------+---------------------------+------+
| eu-1 | EU (Frankfurt)            | Pro  |
| us-1 | US (New York)             | Pro  |
| us-2 | US (San Francisco)        | Pro  |
| ap-1 | Asia Pacific (Singapore)  | Pro  |
| in-1 | India (Bangalore)         | Pro  |
| sa-1 | South America (São Paulo) | Pro  |
| au-1 | Australia (Sydney)        | Pro  |
+------+---------------------------+------+
```

## Changing servers

When you share a local URL, or a local TCP port, you can specify the Expose server region, using the `--server` command line option. Pass the server key as the option to connect to this specific server.

```bash
expose share my-local-site.test --server=eu-1
```

## Setting a default server

Most of the time you will want to always use the server location that is closest to you for all of your Expose commands. You can define the default server that Expose should use, by calling the `expose default-server` command:

```bash
expose default-server us-2
```

Now the next time that you will share a local URL or port, Expose is automatically going to connect to the `us-2` server for your.

---

### Client Magic Authentication (`docs/client/magic-authentication.md`)

---
title: Magic Authentication
order: 5
---

# Sharing sites with magic authentication

Expose allows you to protect your shared sites with a simple email-based authentication flow called "magic authentication". Instead of a browser popup asking for credentials, visitors see a clean login form where they enter their email address. Once submitted, a secure cookie is set allowing access on subsequent requests.

This provides a more user-friendly authentication experience compared to basic authentication, while still providing security for your shared sites.

## Using magic authentication

To share your site with magic authentication that accepts any email address, use the `--magic-auth` flag:

```bash
expose share my-site.test --magic-auth
```

When someone visits your shared URL, they'll see a login form asking for their email address. After entering a valid email, they'll be redirected to the original page and can browse freely for the next 7 days.

## Restricting access by email domain

You can restrict access to specific email domains using the `@domain.com` pattern:

```bash
# Only allow emails from @company.com
expose share my-site.test --magic-auth=@company.com
```

This is useful when sharing development sites with your team - only team members with company email addresses can access the site.

## Restricting access to multiple domains

Separate multiple patterns with commas:

```bash
# Allow emails from @company.com and @partner.com
expose share my-site.test --magic-auth=@company.com,@partner.com
```

## Allowing specific email addresses

You can also allow specific email addresses:

```bash
# Only allow these specific users
expose share my-site.test --magic-auth=alice@example.com,bob@example.com
```

## Combining domains and specific emails

Mix domain patterns and specific email addresses as needed:

```bash
# Allow anyone from @company.com plus a specific contractor
expose share my-site.test --magic-auth=@company.com,contractor@external.com
```

## How it works

1. When a visitor accesses your shared URL without a valid authentication cookie, they see a login form
2. They enter their email address and submit the form
3. If the email matches the allowed patterns (or any email is allowed), a signed cookie is set
4. The visitor is redirected to the original page they requested
5. Future requests include the cookie and pass through to your local site
6. The authentication cookie expires after 7 days

## Connection status

When magic authentication is enabled, the connection table shows the current auth configuration:

```
┌────────────┬──────────────────────────────────────────────┐
│ Shared site│ my-site.test                                 │
│ Dashboard  │ http://127.0.0.1:4040                        │
│ Public URL │ https://my-site.sharedwithexpose.com         │
│ Magic Auth │ Enabled (@company.com)                       │
└────────────┴──────────────────────────────────────────────┘
```

## Combining with other options

Magic authentication works with other sharing options:

```bash
# Custom subdomain with magic auth
expose share my-site.test --subdomain=demo --magic-auth=@company.com

# With custom domain
expose share my-site.test --domain=mycompany.com --magic-auth

# With QR code
expose share my-site.test --magic-auth --qr-code
```

> **Note**: Magic authentication cannot be combined with basic authentication (`--auth`). Choose one authentication method per share session.

---

### Client Sharing Tcp Ports (`docs/client/sharing-tcp-ports.md`)

---
title: Sharing TCP ports
order: 3
---

# Sharing TCP Ports ::pro

Expose not only allows you to share your local development URLs, but you can also use Expose to share any of your local TCP ports.

For example, you might want to share your local copy of [HELO](https://usehelo.com) so that your PHP application can send test emails right through your local SMTP server.

You can share a local TCP port by calling `share-port` followed by the local port number that you want to share:

```bash
expose share-port 2525
```

The Expose server will assign a random TCP port that you can then use on other servers and services to connect to the tunnel.

---

### Client Sharing (`docs/client/sharing.md`)

---
title: Sharing your local sites
order: 1
---

# Sharing local sites

Expose allows you to share any kind of HTTP/HTTPS traffic for websites that you can reach on your own computer, with anyone on the internet.

There are multiple ways to share a site with Expose. 

## Sharing the current working directory

To share the current working directory with Expose, all you need to do is go into the directory and call `expose`.

This makes the assumption that you have access to the current working directory name as a domain with the `.test` TLD.  

If you are using Laravel Valet, the configured Valet subdomain will automatically be detected.

If you are using a different domain for your local sites, you can change the default TLD that expose uses in the [configuration file](/docs/expose/client/configuration).

For example: 

```bash
# Will share a local site "my-site.test" as "my-site.EXPOSE-SERVER"
~/Sites/my-site/ expose

# Will share a local site "api.my-site.test" as "api-my-site.EXPOSE-SERVER"
~/Sites/api.my-site/ expose
```

If you are using the Expose network on the free plan, you get a random subdomain on every connect. You can upgrade to Expose Pro and use custom subdomains as if you'd host your own server.

## Sharing a local site explicitly

If your local sites are not available at `foldername.test` you can explicitly share a local URL, without going into a specific folder first. You can do this by using the `expose share` command and specify the domain directly.

This is required when sharing sites that have HTTPS locally or Expose can't map local directory names to URLs automatically.

```bash
# Will share access to http://192.168.2.100
expose share http://192.168.2.100

# Will share access to http://my-local-site.dev
expose share my-local-site.dev

# Will share access to https://my-local-site.dev
expose share https://my-local-site.dev
```

## Share a local site with a given subdomain ::pro

You can also share one of your local sites explicitly and specify the exact subdomain that you want to use when sharing the site. This is very useful if you are testing webhooks and want to use the same webhook configuration and don't update the webhook endpoints on every Expose connect. Custom subdomains require an own Expose server in your infrastructure or Expose Pro.

To specify the subdomain, pass the `--subdomain` option to expose:

```bash
expose share my-site.test --subdomain=my-site
```

If someone already uses the chosen subdomain on the Expose server, you will see an error message and the Expose server closes the connection.

---

### Extending The Server Custom Views (`docs/extending-the-server/custom-views.md`)

---
title: Custom Views
order: 3
---

# Custom Views

## Homepage

The expose server allows you to modify the "homepage" of your server. This is the website that will be shown to your users when you access your server without any subdomain.

To customize it, clone the repository and modify the file located at `resources/views/homepage.twig`.

## 404 - Tunnel not found

Just like the homepage, you can also modify 404 views in case someone tries to access a subdomain that is not registered on the expose server.

To customize the error view, clone the repository and modify the file located at `resources/views/errors/404.twig`.

---

### Extending The Server Subdomain Generator (`docs/extending-the-server/subdomain-generator.md`)

---
title: Subdomain Generator
order: 1
---

# Subdomain Generator

When a user does not explicitly specify a custom subdomain, the expose server takes care of generating a random unique subdomain.

The default generator looks like this:

```php
use Illuminate\Support\Str;
use Expose\Client\Contracts\SubdomainGenerator;

class RandomSubdomainGenerator implements SubdomainGenerator
{
    public function generateSubdomain(): string
    {
        return strtolower(Str::random(10));
    }
}
```

It simply generates a random lowercase string.

You can create your own custom subdomain generator class, by implementing the `SubdomainGenerator` interface.

Next you need to specify your custom subdomain generator in your expose configuration file:

```php
/*
|--------------------------------------------------------------------------
| Subdomain Generator
|--------------------------------------------------------------------------
|
| This is the subdomain generator that will be used, when no specific
| subdomain was provided. The default implementation simply generates
| a random string for you. Feel free to change this.
|
*/
'subdomain_generator' => \Expose\Client\Server\SubdomainGenerator\RandomSubdomainGenerator::class,
```

---

### Extending The Server User Repository (`docs/extending-the-server/user-repository.md`)

---
title: User Repository
order: 2
---

# User Repository

The expose server tries to load users out of the built-in SQLite database by default. 

If you want to change the default implementation and load your users from a different storage engine, you can implement the `UserRepository` interface and change it in your expose configuration file.

This is how the interface looks like:

```php
use React\Promise\PromiseInterface;

interface UserRepository
{
    public function getUsers(): PromiseInterface;

    public function getUserById($id): PromiseInterface;

    public function getUserByToken(string $authToken): PromiseInterface;

    public function storeUser(array $data): PromiseInterface;

    public function deleteUser($id): PromiseInterface;
}
```

---

### Getting Started Getting Your Token (`docs/getting-started/getting-your-token.md`)

---
title: Setup Your Token
order: 2
---

# Setup your authentication token

If you are using our managed Expose server infrastructure, you can obtain a free authentication token by [creating an account](https://expose.dev/register).

After logging in to Expose for the first time, you will see the installation steps for Expose, as well as your authentication token.
Copy the command to your clipboard to setup your authentication token.

---

### Getting Started Installation (`docs/getting-started/installation.md`)

---
title: Installation
order: 1
---

# Installation

## PHP Archive (PHAR)
We distribute Expose as a PHAR archive that contains everything you need in order to use Expose. Simply download it from [here]() and make it executable:

```
wget -O expose https://link-to-expose

chmod +x expose

./expose
```

You most likely want to put the `expose` program into a directory on your `PATH`, so you can simply call expose from any directory. For example:

```
sudo mv expose /usr/local/bin/expose
```

After that, you are ready to go and can [share your first site](/docs/getting-started/sharing-your-first-site).
 
## Via Composer
Expose is a PHP application and you can install the client for your local machine as a global composer dependency:

```bash
composer global require beyondcode/expose
```

Make sure that your global composer directory is inside of your `PATH` environment variable.
Simply add this directory to your `PATH` in your `~/.bash_profile` (or `~/.bashrc`) like this:

```
export PATH=~/.composer/vendor/bin:$PATH
```

## As a docker container

Expose has a `Dockerfile` in the root of the source that you can build and use without any extra effort.

```bash
docker build -t expose .
```

Usage:

```bash
docker run expose <expose command>
```

Examples:

```bash
docker run expose share http://192.168.2.100 # share a local site
docker run expose serve my-domain.com # start a server
```

Now you're ready to go and can [share your first site](/docs/expose/getting-started/sharing-your-first-site).


### Extending Expose

By default, Expose comes as an executable PHAR file. This allows you to use all Expose features out of the box – without any additional setup required.

If you want to modify Expose and want to add custom request/response modifiers, you need to clone the GitHub repository instead of the global composer dependency.

You can learn more about the customization of Expose in the [extending Expose](/docs/expose/extending-the-server/subdomain-generator) documentation section.

---

### Getting Started Questions Issues (`docs/getting-started/questions-issues.md`)

---
title: Questions & Issues
order: 3
---

# Questions and issues

Find yourself stuck using the package? Found a bug? Do you have general questions or suggestions for improving Expose? Feel free to create an issue on [GitHub](https://github.com/beyondcode/expose/issues), we'll try to address it as soon as possible.

If you've found a bug regarding security please mail [marcel@beyondco.de](mailto:marcel@beyondco.de) instead of using the issue tracker.

---

### Getting Started Sharing Your First Site (`docs/getting-started/sharing-your-first-site.md`)

---
title: Share your first site
order: 2
---

# Share your first site

Once your authentication token is setup, you are ready to share your first site with Expose.
Expose creates a tunnel between your local development URLs/HTTP server and a publicly available web server.

The easiest way to share your local URLs is by calling `expose share` followed by the local URL that you want to share:

```bash
# Will share access to http://192.168.2.100
expose share http://localhost:3000

# Will share access to http://my-local-site.dev
expose share my-local-site.dev
```

By default, Expose assumes that you want to share unenecrypted local traffic through HTTP. If you want to share a local HTTPS URL prepend the protocol to the url, like this:

```bash
# Will share access to https://my-local-site.dev 
# Note the https for tunneling locally encrypted sites
expose share https://my-local-site.dev
```

## Custom Subdomains ::pro

To make your life easier, Expose tries to share your local URLs using custom subdomains. This allows you to share your local URL `my-local-site.dev` as `my-local-site.us-1.sharedwithexpose.com`.

By default, Expose uses a slugified version of the URL that you want to share, but you can also [choose your own custom subdomain](/docs/client/sharing#share-a-local-site-with-a-given-subdomain).

---

### Release Notes 2 0 0 (`docs/release-notes/2-0-0.md`)

---
title: Expose 2.0
order: 999
---

# Expose 2.0 🥳

Almost one year after the initial release of Expose 1.0.0, we are extremely excited about the release of version 2.0! 
In addition to the release of Expose 2.0 as open source software, we have also released Expose Pro - a commercial offering of all the latest and greatest Expose features on a global network of Expose servers.

We have put a ton of effort into this release, making sure that Expose stays the best tunneling solution out there - not only for PHP developers.

## New Features

### Dark Mode 🌚

The local Expose Dashboard now comes with a beautiful dark mode theme!



### Automatic Subdomain Generation

When sharing a local site explicitly via `expose share my-local-site.test`, Expose 2 now automatically assigns a static subdomain based on the provided hostname. In this case, Expose would try to use the subdomain `my-local-site`. This makes it even easier to always ensure that you use the same subdomain for your Expose URLs, even if you do not explicitly provide the custom subdomain yourself.

### TCP Port Sharing

Expose 2.0 finally adds the ability to share your local TCP ports with others. This is super useful when you want to give access to an application that is running on your local machine via an Expose server.

For example, you can share your local [HELO](https://usehelo.com) instance with others, making it easy to send out emails from staging/production servers right into a desktop application running on your local computer.

### Reserved Subdomains

In Expose 1.0 you were already able to specify a custom subdomain that you want to use for your current tunnel. With Expose 2.0 you can now ensure that nobody else can use the subdomain besides you (and your team). You can reserve a custom subdomain on an Expose server and this subdomain will then be associated with your unique authentication token. 

### Multiple-Server support

Expose 1.0 was limited to one server that it could connect to. In case of our free Expose server, this would mean that all traffic was going through one server sitting in Frankfurt, Germany. With Expose 2.0, you can now define an array of servers that are available for your Expose client and then easily switch between those servers using the `--server` command-line argument.

### White-Label Domain support

The 2.0 update of Expose finally allows you to register a custom white-label domain on the Expose servers, allowing you to use your own custom domain with the Expose service. This means that you no longer have to share `*.sharedwithexpose.com` URLs with your colleagues and clients, but you can now register your own domain and use that instead. All it takes is a simple CNAME DNS entry and you're ready to go!

White label domains get TLS/SSL certificates on the first connect to a URL automatically. This process takes a few seconds so that first page load can take a moment or even fail – try again after a few seconds and all additional requests will be fast until the certificate expires. Re-using the same (sub-)domain makes sure that your certificate stays available.

---

### Server Admin Interface (`docs/server/admin-interface.md`)

---
title: Admin Interface
order: 3
---

# Admin Interface

The Expose server comes with a beautiful admin interface that makes configuring your server a breeze.

The admin interface is available at a specific subdomain on your expose server. By default it is called "expose", but you can change this in the configuration file:

```
...

/*
|--------------------------------------------------------------------------
| Subdomain
|--------------------------------------------------------------------------
|
| This is the subdomain that your expose admin dashboard will be available at.
| The given subdomain will be reserved, so no other tunnel connection can
| request this subdomain for their own connection.
|
*/
'subdomain' => 'expose',

...
```

So you can reach the admin interface at http://expose.your-domain.com.

## Authentication

Since the expose admin interface allows you to change and modify your expose server configuration at runtime, access to the admin interface is protected using basic authentication.
You can define which user/password combinations are allowed in the configuration file:

> **Note:** You will need to restart your expose server once you change this setting in order for the changes to take effect.

```
...

/*
|--------------------------------------------------------------------------
| Users
|--------------------------------------------------------------------------
|
| The admin dashboard of expose is protected via HTTP basic authentication
| Here you may add the user/password combinations that you want to
| accept as valid logins for the dashboard.
|
*/
'users' => [
    'username' => 'password'
],

...
```

### Users



Here you can list, add and delete all users that you want to be able to connect to your expose server. 
The users will be stored in a SQLite database that can be modified in the expose configuration file.

You only need to add users to your expose server if you have the auth token validation enabled.

### Shared sites



You can see a list of all connected sites here once you and others start sharing their local sites with your server.
You can see the original client host that was shared, the subdomain that was associated to this and the time and date the site was shared.

The expose server can also disconnect a site from the server. Just press on the "Disconnect" button and the client connection will be closed.

### Settings



Here you can see and modify your Expose server settings. All settings that the UI offers can also be manually edited in the expose configuration file.

---

### Server Server Configuration (`docs/server/server-configuration.md`)

---
title: Server Configuration
order: 5
---

# Server Configuration

Within the Expose admin interface you can configure how you want your specific expose server to behave.

Here are the available settings:



## Authentication

When you start your expose server, anyone is able to connect to it by default. If you want to restrict your server only to users that have a valid "authentication token", you can simply check the checkbox. Only registered users / authentication tokens are then able to connect to your server.

> **Note:** This is only a temporary modification for as long as your expose server is running. To permanently enable this feature, modify your expose config file.

## Message of the day

This message will be shown when a successful connection to the expose server can be established. You can change it on demand, or modify it permanently in your expose configuration file.

## Maximum connection length

You can define how long you want your users connection to your expose server to be open at maximum. This time can be configured in minutes. Once the connection exceeds the specified duration, the client connection gets closed automatically.

## Authentication failed

This message will be shown when a user tries to connect with an invalid authentication token. If your users can somehow obtain an authentication token, this is a great place to let them know how to do it.

## Subdomain taken

This message will be shown when a user tries to connect with an already registered subdomain. This could be any user-registered subdomain, as well as the expose admin dashboard subdomain.

---

### Server Ssl (`docs/server/ssl.md`)

---
title: SSL Support
order: 2
---

# SSL Support

Once your Expose server is running, you can only access it over the port that you configure when the server gets started.

If you want to enable SSL support, you will need to use a proxy service - like Nginx, HAProxy, Apache2 or Caddy - to handle the SSL configurations and proxy all non-SSL requests to your expose server.

## Nginx configuration

A basic Nginx configuration would look like this, but you might want to tweak the SSL parameters to your liking.

```
server {
  listen        443 ssl;
  listen        [::]:443 ssl;
  server_name   expose.yourapp.tld;

  # Start the SSL configurations
  ssl                  on;
  ssl_certificate      /etc/letsencrypt/live/expose.yourapp.tld/fullchain.pem;
  ssl_certificate_key  /etc/letsencrypt/live/expose.yourapp.tld/privkey.pem;

  location / {
    proxy_pass             http://127.0.0.1:8080;
    proxy_read_timeout     60;
    proxy_connect_timeout  60;
    proxy_redirect         off;

    # Allow the use of websockets
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
  }
}
```

## Apache2 configuration

A basic Apache configuration would look like this, but you might want to tweak the SSL parameters to your liking.

```
Listen 80
Listen 443

<IfModule mod_ssl.c>
<VirtualHost *:443>
	ServerName expose.domain.tld
	ServerAlias *.expose.domain.tld
	LoadModule        proxy_module            modules/mod_proxy.so
	LoadModule        proxy_http_module       modules/mod_proxy_http.so

	ServerAdmin admin@domain.tld

	ProxyPass "/" "http://localhost:8080/"
	ProxyPassReverse "/" "http://localhost:8080/"
	ProxyPreserveHost On
	

	# Needed for websocket support
	RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC,OR]
	RewriteCond %{HTTP:CONNECTION} ^Upgrade$ [NC]
	RewriteRule .* ws://127.0.0.1:8080%{REQUEST_URI} [P,QSA,L]

	<Proxy http://localhost:8080>

		Require all granted

		Options none
	</Proxy>

	ErrorLog ${APACHE_LOG_DIR}/expose.domain.tld-error.log
	CustomLog ${APACHE_LOG_DIR}/expose.domain.tld-access.log combined

	SSLCertificateFile /etc/letsencrypt/live/expose.domain.tld-0001/fullchain.pem
	SSLCertificateKeyFile /etc/letsencrypt/live/expose.domain.tld-0001/privkey.pem
	Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>
```

---

### Server Starting The Server (`docs/server/starting-the-server.md`)

---
title: Starting the server
order: 1
---

# Starting the server

Expose is open source and you can host your own Expose server in your own infrastructure. The open source core contains the server and the client but does not include the Expose platform where you can manage your team, reserve subdomains or add custom domains via the web interface.

The expose binary that you install via composer contains both the server and the client, so you do not need any additional software for this to work.

Once you have successfully downloaded expose, you can start the server using this command:

````bash
expose serve my-domain.com
````

This will start listening for incoming expose client connections on port 8080 by default.

If you want, you can customize the port:

```bash
expose serve my-domain.com --port=3000
```

## Validating auth tokens

When you start your expose server, anyone is able to connect to it by default. If you want to restrict your server only to users that have a valid "authentication token", you can start the server with the `--validateAuthTokens` option:

```bash
expose serve my-domain.com --validateAuthTokens
```

Don't worry - you can also change this later on through the admin interface.

## Keeping the expose server running with supervisord

The `expose serve` daemon needs to always be running in order to accept connections. This is a prime use case for `supervisor`, a task runner on Linux.

First, make sure `supervisor` is installed.

```bash
# On Debian / Ubuntu
apt install supervisor

# On Red Hat / CentOS
yum install supervisor
systemctl enable supervisord

# On Mac
brew install supervisor
```

Once installed, add a new process that `supervisor` needs to keep running. You place your configurations in the `/etc/supervisor/conf.d` (Debian/Ubuntu) or `/etc/supervisord.d` (Red Hat/CentOS) directory.

Within that directory, create a new file called `expose.conf`.

```bash
[program:expose]
command=/usr/bin/php /home/expose/expose serve
numprocs=1
autostart=true
autorestart=true
user=forge
```

Once created, instruct `supervisor` to reload its configuration files (without impacting the already running `supervisor` jobs).

```bash
supervisorctl update
supervisorctl start expose
```

Your expose server should now be running (you can verify this with `supervisorctl status`). If it were to crash, `supervisor` will automatically restart it.

Please note that, by default, `supervisor` will force a maximum number of open files onto all the processes that it manages. This is configured by the `minfds` parameter in `supervisord.conf`.

If you want to increase the maximum number of open files, you may do so in `/etc/supervisor/supervisord.conf` (Debian/Ubuntu) or `/etc/supervisord.conf` (Red Hat/CentOS):

```
[supervisord]
minfds=10240; (min. avail startup file descriptors;default 1024)
```

After changing this setting, you'll need to restart the supervisor process (which in turn will restart all your processes that it manages).


## Connecting the client

To configure a client to connect to your custom server, first [publish the configuration file](/docs/expose/client/configuration) on the client. Once that is done, you can change the `host` and `port` configuration values on your client.

```php
return [

    /*
    |--------------------------------------------------------------------------
    | Host
    |--------------------------------------------------------------------------
    |
    | The expose server to connect to. By default, expose is using the free 
    | sharedwithexpose.com server, offered by Beyond Code. You will need a free
    | Beyond Code account in order to authenticate with the server.
    | Feel free to host your own server and change this value.
    |
    */
    'host' => 'my-domain.com',

    /*
    |--------------------------------------------------------------------------
    | Port
    |--------------------------------------------------------------------------
    |
    | The port that expose will try to connect to. If you want to bypass 
    | firewalls and have proper SSL encrypted tunnels, make sure to use
    | port 443 and use a reverse proxy for Expose. 
    |
    | The free default server is already running on port 443.
    |
    */
    'port' => 3030,

    // ...
```

## Running With Docker

To run Expose with docker use the included `docker-compose.yaml`. Copy `.env-example` to `.env` and update the configuration.

```
PORT=8080
DOMAIN=example.com
ADMIN_USERNAME=username
ADMIN_PASSWORD=password
```

After updating the environment variables you can start the server:

```bash
docker-compose up -d
```

Now that your basic expose server is running, let's take a look at how you can add SSL support.

---

--- METRICS ---
- Files Extracted: 26
- Estimated Token Budget: ~10448 tokens
- Canonical Reference: https://codewiki.google/github.com/exposedev/expose
