TheGreydiamonds Blog

Year: 2023

Enabling “hosted” features in outline

Attention

The initial guide stopped working as of version v0.72.0 due to PR#5742 which removed the variables from the .env file. I’ve updated this article to include the new way of enabling these features – but kept the old text.

A few days ago I discovered a nice Notion alternative called “Outline“. It seemed to provide a nice feature set while also being self-hosted. The setup was somewhat cumbersome, as it needs an S3 Object storage, auth provider, postgres DB and Redis server. After setting up Keycloak for auth and MinIO for S3 Object storage I was ready to go.

But there was one thing missing I knew from Notion—multiple workspaces and switching between them. The UI looked like it supported context switching, though no “Create New Workspace” can be found. Digging through the web demo I found the function. The hosted version seems to support it while the self-hosted doesn’t weird. After looking through Outline’s Github issues I discovered someone complaining about a semi-working “Create workspace” button.

A screenshot of the working "New Workspace" button in Outline
A screenshot of the working “New Workspace” button

Configuration options to get Outline working

Most configuration is done using the .env file. One option which caused the semi-working button to show up was DEPLOYMENT=hosted. And I was able to confirm this aforementioned behaviour. Indeed a “Create Workspace”-button showed up. Creating a new Workspace, however, caused weird behaviour where I was trapped in the new Workspace, unable to switch.

Looking through the source code there was another interesting option SUBDOMAINS_ENABLED=true. Huh, I wonder what this does I thought while flicking it on.

Upon visiting the outline subdomain I was greeted with a redirect to a subdomain <workspace>.outline.domain.tld. This felt like the final stretch. I made a new certificate for *.outline subdomains and set up nginx to point them to the application as well.

And boom – I got a “hosted-only” feature working on a self-hosted instance.

Cool – but how to enable these features?

Before version v0.72.0 these features could be enabled by changing variables in the .env file. As of PR#5742 this no longer works and code modification is required.

There are two points in the source code where the system decides whether or not it is running a “cloud-hosted” environment. We need to modify the code, to make it think that we always run in such a hosted env.

Begin by modifying the file “app/utils/isCloudHosted.ts” where you need to replace these lines:

const isCloudHosted = [
  "https://app.getoutline.com",
  "https://app.outline.dev",
  "https://app.outline.dev:3000",
].includes(env.URL);

with this single line:

const isCloudHosted = true;

Next edit the file “server/env.ts”, where you replace:

public get isCloudHosted() {
    return [
      "https://app.getoutline.com",
      "https://app.outline.dev",
      "https://app.outline.dev:3000",
    ].includes(this.URL);
  }

with this simple bit:

public get isCloudHosted() {
    return true;
}

These are all the steps necessary in order to get these hosted features back.

After that you have to run yarn build.
(This is really important and more a note for future me…)

Cool – but how do I do it? – The old (and broken) way

First, add these lines to your configuration:

DEPLOYMENT=hosted
SUBDOMAINS_ENABLED=true

Now make sure you have SSL certificates for the subdomain you want to use. In my case *.outline.domain.tld. You can use certbot with the cloudflare-dns-challenge plugin to request fitting certificates.

Next, you need to configure your nginx webserver to properly handle the new request.

This is the config I’m using. This might not be perfect for your installation but should probably also work.

I hope this helps someone out there and saves them at least a little time!

A first go at projection mapping – What we’ve learned

A few months ago (at Halloween to be specific) a friend of mine and I had the idea to do some projection mapping after licking blood while doing a small-scale test at his house (link coming soon). We came up with the idea of projection onto the front of my school. “Yea sure”, I sarcastically replied. However, a few weeks later I came back to the idea and we decided that we wanted to have a go at it.

I didn’t think I’d get this far

The first step was convincing my school to allow me to do it. I talked to one of my favourite teachers about the idea first and he seemed to like it. So I made an appointment with our headteacher. And after presenting the idea he was all for it. That was easier than expected. The biggest issue was getting power to the front of our school – in the middle of the school holidays. Oh yeah did I mention that we decided to do it on New years eve?

The next important step was getting equipment. My friend could get two crappy projectors from his school. That was not nearly enough. So I reached out to the boss of a local event tech company who I knew. He swiftly agreed to give me his biggest projector (with a lens!) for free for a few days.

Due to some concerns we also reached out to MSS-Security, a local security company and they agreed to be there for the evening if we advertise them in some way.

So now we had:

  • four projectors
  • a PA system (shout-out to wentbeatz btw)
  • power in front of our school (courtesy of our cool custodian)
  • and a (hopefully) sturdy tent (foreshadowing….)

Now that we had all components together it was time to start making content.

Making content

The first step was to get a rough idea of how to lay out the content. So I headed out to create a 3D scan of the school. That worked semi-well. Turns out 500 photos are bearly enough. The model had a lot of holes and looked more like swiss cheese rather than a proper model. After importing that model into Blender we created an orthographic render of the building.

A guide we used to align media with the building

We quickly decided on how we wanted to lay out the show time-wise. It should contain some narration and music-driven elements. Most content was created by XilefTech due to the simple fact of me being very busy.

Additionally, we only created the content a few days before the event. So if we were to do it again, we would need to take a lot more time for content preparation. This time crunch lead to us having the remove a segment because it decided to not render at the last minute and we had no time to try and debug it.

Finally, we put everything into MadMapper. MadMapper allowed us to easily combine the pre-rendered content with render-on-the-fly content. So while no preprepared show was running we could create content on the fly without much worry. We rented a one-seat license for just that event. Some time ago we reached out to MadMapper in the hope to get some kind of sponsorship, sadly they responded to us that they stopped sponsoring artists (in the most generic E-Mail template there is…).

Running the event

Due to the sheer amount of stuff, we had to transport we needed to take two car rides. On our first go, we brought a tent and some speakers which I set up while my colleague went to get the next load. We set aside around one and a half hours for setup. After setting up the tent and our speakers the next step on our list was to set up our big 20.000 ANSI Lumen Panasonic Projector. After placing it in a central spot and adjusting it we were blown away by how much it actually covered. We had done our fair share of maths beforehand and were always a little scared of not having enough projectors.

We ran the setup with two laptops, only giving us two outputs. You might have noticed there is a small mismatch between the number of projectors we have and the outputs we can provide. So we brought two Raspberry PIs to act as NDI receivers. We were running Dicaffine, and it worked for the most part, though it seems like even small drop-outs cause it to lose connection completely. The official NDI tools are sadly not available for Linux. We briefly considered using Windows IoT, however, we couldn’t get it working in time. We’ve conducted tests beforehand and it had always worked “fine”, however, something was not running well that evening. The Pis were cutting out most of the time. It didn’t hurt the show too much as they were providing data to the two weak projectors to the left and right of our projection area.

In retrospect using two not-that-high-power laptops wasn’t a very splendid idea either. However, it mostly worked. Running some content we had stuttering issues due to the power of the laptop. We had another stronger laptop with us, however, it had issues providing data to our main projectors. The projector supported some kind of 3D projection. Windows did really not like that.

Apart from some minor performance issues, the evening went through okay. We were semi-lucky with the weather. It had just stopped raining in the early noon and everything looked fine. However, there were some strong wind gusts which we thought of as non-issues. Turned out we were pretty wrong about that. After about half the time our tent was blown away, we managed to catch it before flying off, though one of the primary stands of the tent broke.

Summary

We all really enjoyed the evening. However, if we were to do it again, we would need a whole lot more time for preparation and a little more capable equipment. We even managed to get a shoutout on my school’s website (link to the article, german).

Gallery

Here are a few impressions of the evening and a video:

© 2025 Thegreydiamond

Theme by Anders NorenUp ↑