# Install Discourse on an isolated CentOS 7 server

**URL:** https://meta.discourse.org/t/install-discourse-on-an-isolated-centos-7-server/73538
**Category:** Sysadmins
**Tags:** how-to, install
**Created:** [November 6, 2017, 5:16pm UTC](https://meta.discourse.org/t/install-discourse-on-an-isolated-centos-7-server/73538 "2017-11-06T17:16:03Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![nil4](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nil4/32/81796_2.png) [@nil4](https://meta.discourse.org/u/nil4)
#### Post date: [November 6, 2017, 5:16pm UTC](https://meta.discourse.org/t/install-discourse-on-an-isolated-centos-7-server/73538/1 "2017-11-06T17:16:03Z")

</div>

Here is what worked for me to install Discourse on an isolated CentOS 7 server. In a nutshell, on a machine with internet access I prepared:

1. the Git repos that Discourse setup needs: `SamSaffron/pups`, `discourse/discourse`, `discourse/discourse_docker` and `discourse/docker_manager`.
2. the two Docker images: `discourse/base` and `samsaffron/docker-gc`
3. the complete Ruby Gem cache that `bundle install` downloads during bootstrap.

I copied these to the isolated server, and used them to install offline; below are the full details.I hope this helps.

### 1. Preparation on a machine with internet access

With Docker-CE and Git installed, run these commands:

```shell
mkdir -p ~/local/github.com
mkdir -p ~/local/rubygems.org
mkdir -p ~/local/docker-images

# 1
git clone --bare https://github.com/SamSaffron/pups.git ~/local/github.com/SamSaffron/pups.git
git clone --bare https://github.com/discourse/discourse.git ~/local/github.com/discourse/discourse.git
git clone --bare https://github.com/discourse/discourse_docker.git ~/local/github.com/discourse/discourse_docker.git
git clone --bare https://github.com/discourse/docker_manager.git ~/local/github.com/discourse/docker_manager.git

#2
sudo mkdir -p /var/discourse
sudo git clone https://github.com/discourse/discourse_docker.git /var/discourse

```

Step #1 clones the required Discourse GitHub repositories locally.

Step #2 prepares for the local installation of Discourse, which must run once, to extract Ruby GEMs from the Discourse image (step #4 below).

Search `/var/discourse/launcher` to find the line starting with `image=discourse/base` e.g.:

```plaintext
image=discourse/base:2.0.20171008

```

Two Docker images are needed: `discourse/base` with the version above, and `docker-gc`. To get them locally, run:

```bash
#3
docker pull discourse/base:2.0.20171008
docker pull samsaffron/docker-gc
docker save -o ~/local/docker-images/discourse_base discourse/base:2.0.20171008
docker save -o ~/local/docker-images/docker-gc samsaffron/docker-gc

```

Step #3 downloads the images and exports them to files under `~/local/docker-images/`.

The `~/local` folder now has local copies of the Discourse code, and Docker images required for installation.

However, local copies of the Ruby GEMs that Discourse downloads as part of its bootstrap process are still needed. IMHO it would be much easier if they were just included in the `discourse/base` Docker image.

Discourse needs to be bootstrapped to get these files. [Follow the official instructions](https://github.com/discourse/discourse/blob/master/docs/INSTALL-cloud.md), _but stop at the **Start Discourse** step_. That is, configure and bootstrap Discourse, up to the point where the Docker container `local_discourse/app` is created.

Then run the following commands:

```bash
# 4
docker run -it -v ~/local/rubygems.org:/local-rubygems local_discourse/app /bin/bash
# the commands below run inside the Discourse 'app' container
cp -r /var/www/discourse/vendor/bundle/ruby /local-rubygems 
exit

```

Step #4 copies the full Ruby GEM cache out of the Discourse image into the `~/local/rubygems.org` folder.

Now everything required to set up Discourse offline is available in the `~/local` folder. Copy this folder to the target machine.

### 2. Install Discourse on the target machine, with no internet access

Copy the `~/local` folder prepared above to the target machine that has no internet access, e.g. to `/root/local`.

You will need to be `root` through the rest of the setup and bootstrap process:

```bash
sudo -s

```

Import the two Docker images:

```bash
docker load -i /root/local/docker-images/discourse_base
docker load -i /root/local/docker-images/docker-gc

```

Configure Git to use the `/root/local/github.com/` folder instead of going out to `https://github.com/`:

```bash
git config --global url."file:///root/local/github.com/".insteadOf https://github.com/

```

Create the Discourse folder and clone `discourse_docker.git` there:

```bash
mkdir -p /var/discourse
git clone https://github.com/discourse/discourse_docker.git /var/discourse/

```

Run `./discourse-setup` to generate your Discourse configuration. At the end of the configuration process, when you see the message _Updates successful. Rebuilding in 5 seconds._, press `Ctrl+C`.

```bash
cd /var/discourse/
./discourse-setup

```

Edit the `/var/discourse/launcher` file and disable updating `pups` (the version bundled with Discourse will be used instead), changing from:

```bash
  if [[! "false" = $update_pups]]; then
    run_command="$run_command git pull &&"
  fi

```

to:

```bash
# if [[! "false" = $update_pups]]; then
# run_command="$run_command git pull &&"
# fi

```

Edit the `/var/discourse/containers/app.yml` file and update the `volumes` section as follows:

```yaml
volumes:
  # these two volumes are already defined
  - volume:
      host: /var/discourse/shared/standalone
      guest: /shared
  - volume:
      host: /var/discourse/shared/standalone/log/var-log
      guest: /var/log
  # ADD THE TWO VOLUMES BELOW, making the local copies of github.com repos and Ruby GEM cache
  # available inside the Discourse container when it is built
  - volume:
      host: /root/local/github.com
      guest: /local-github.com
  - volume:
      host: /root/local/rubygems.org
      guest: /local-rubygems.org

```

This makes the local GitHub repo clones, and the Ruby GEM cache, available to the Discourse container.

Edit the `/var/discourse/templates/web.template.yml` file, and make the following changes.

**(1)** Disable updating Bundler (using the version bundled with Discourse instead) by commenting-out the `gem update bundler` line, from:

```yaml
  - exec:
      cd: $home
      hook: web
      cmd:
        # ensure we are on latest bundler
        - gem update bundler
        - chown -R discourse $home

```

to:

```yaml
  - exec:
      cd: $home
      hook: web
      cmd:
        # ensure we are on latest bundler
        #- gem update bundler
        - git config --global url."file:///local-github.com/".insteadOf https://github.com/
        - chown -R discourse $home

```

Instead of updating bundler, Git (the one inside the container) is configured to use the local folder instead of going out to `https://github.com/`.

**(2)** Configure `bundle install` to use the **local** Ruby GEM cache and not connect to `rubygems.org` by changing these lines from:

```yaml
  - exec:
      cd: $home
      hook: bundle_exec
      cmd:
        - su discourse -c 'bundle install --deployment --verbose --without test --without development'
        - su discourse -c 'bundle exec rake db:migrate'
        - su discourse -c 'bundle exec rake assets:precompile'

```

to:

```yaml
  - exec:
      cd: $home
      hook: bundle_exec
      cmd:
        # copy the locally-cached Ruby GEMS to /var/www/discourse/vendor/...
        - cp -rv /local-rubygems.org/ $home/vendor/bundle/ruby/
        # install GEMs from local cache only, using `--local` (see http://bundler.io/v1.15/bundle_install.html)
        - su discourse -c 'bundle install --local --deployment --verbose --without test --without development'
        - su discourse -c 'bundle exec rake db:migrate'
        - su discourse -c 'bundle exec rake assets:precompile'

```

And that’s it. Run `./launcher bootstrap app` and, hopefully, enjoy your offline Discourse!

---

<div class="post-metadata">

### Author: ![fefrei](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/fefrei/32/119538_2.png) [@fefrei](https://meta.discourse.org/u/fefrei)
#### Post date: [November 7, 2017, 8:11am UTC](https://meta.discourse.org/t/install-discourse-on-an-isolated-centos-7-server/73538/2 "2017-11-07T08:11:45Z")

</div>

This may be a very naive question, but… couldn’t you just move the bootstrapped container to the offline server instead of capturing all the Gems necessary to bootstrap there?

---

<div class="post-metadata">

### Author: ![nil4](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nil4/32/81796_2.png) [@nil4](https://meta.discourse.org/u/nil4)
#### Post date: [November 7, 2017, 9:24am UTC](https://meta.discourse.org/t/install-discourse-on-an-isolated-centos-7-server/73538/3 "2017-11-07T09:24:58Z")

</div>

Unfortunately that did not work for me. The container Discourse runs in is not isolated from its host; the database, uploads, backups, etc. are stored in volumes mapped to the host file system. You need to copy those as well, and when I copied the bootstrapped container from another machine, I could not line up the file permissions between the users inside the container and those on the host.

See also the comments in the related thread [Discourse in a closed intranet](https://meta.discourse.org/t/discourse-in-a-closed-intranet/42449)

Another issue is that the launcher script does upgrades (Postgress DB migrations, for example) when time comes to update the Discourse version.

With this approach, I can simply update the local copies of Git repos and base Docker images, then run `./launcher rebuild app` and let it handle the upgrade correctly.

---

<div class="post-metadata">

### Author: ![riking](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/riking/32/170938_2.png) [@riking](https://meta.discourse.org/u/riking)
#### Post date: [November 19, 2017, 1:54am UTC](https://meta.discourse.org/t/install-discourse-on-an-isolated-centos-7-server/73538/4 "2017-11-19T01:54:56Z")

</div>

Be aware that you will have to manually check for security updates; because the code cannot reach [discourse.org](http://discourse.org) for version checks it cannot email you when updates are available.

There’s several other features that assume full internet connectivity, but I expect you’re prepared to deal with not having those.

---

<div class="post-metadata">

### Author: ![nil4](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nil4/32/81796_2.png) [@nil4](https://meta.discourse.org/u/nil4)
#### Post date: [November 26, 2017, 11:23pm UTC](https://meta.discourse.org/t/install-discourse-on-an-isolated-centos-7-server/73538/5 "2017-11-26T23:23:11Z")

</div>

Thanks @riking, that’s right. Fortunately upgrading seems pretty straightforward, unless I am missing something.

On the connected PC, run `git fetch --all` on the Git repos, rebuild Discourse, extract Ruby Gem cache, and if needed export newer versions of the Docker images. Then copy these over and run `./launcher rebuild app`.

---

<div class="post-metadata">

### Author: ![ssvenn](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ssvenn/32/86740_2.png) [@ssvenn](https://meta.discourse.org/u/ssvenn)
#### Post date: [May 29, 2018, 7:53pm UTC](https://meta.discourse.org/t/install-discourse-on-an-isolated-centos-7-server/73538/6 "2018-05-29T19:53:55Z")

</div>

> [@nil4](#):
>
> Edit the `/var/discourse/templates/web.template.yml` file, and make the following changes.
> 
> **(1)** Disable updating Bundler (using the version bundled with Discourse instead) by commenting-out the `gem update bundler` line, from:
> 
> ```plaintext
> - exec:
> cd: $home
> hook: web
> cmd:
> # ensure we are on latest bundler
> - gem update bundler
> - chown -R discourse $home
> 
> ```
> 
> to:
> 
> ```plaintext
> - exec:
> cd: $home
> hook: web
> cmd:
> # ensure we are on latest bundler
> #- gem update bundler
> - git config --global url."file:///local-github.com/".insteadOf https://github.com/
> - chown -R discourse $home
> 
> ```

This doesn’t work for me, there is an earlier step in this template where git tries to connect to the internet and fails

the way to do it seems to be to change this earlier block from:

```plaintext
  - exec:
      cd: $home
      hook: code
      cmd:
        - git reset --hard
        - git clean -f
        - git remote set-branches --add origin master

```

to:

```plaintext
  - exec:
      cd: $home
      hook: code
      cmd:
        - git reset --hard
        - git clean -f
        - git config --global url."file:///local-github.com/".insteadOf https://github.com/
        - git remote set-branches --add origin master

```

and I had to modify the path when copying the ruby GEMs, like this:

```plaintext
      # copy the locally-cached Ruby GEMS to /var/www/discourse/vendor/...
        - cp -rv /local-rubygems.org/ruby/* $home/vendor/bundle/ruby/

```

Otherwise they would get copied too deep and the bootstrap fails:

```plaintext
'/local-rubygems.org/ruby/2.4.0' -> '/var/www/discourse/vendor/bundle/ruby/local-rubygems.org/ruby/2.4.0'`
etc
I, [2018-05-29T19:33:47.678827 #5] INFO -- : Running `bundle install --deployment --local --verbose --without "development"` with bundler 1.16.1
Frozen, using resolution from the lockfile
The definition is missing ["fastimage-2.1.1", "libv8-6.3.292.48.1", "mini_racer-0.1.15"]
Could not find fastimage-2.1.1 in any of the sources

```

It also seems like upgrading an existing installation from postgres 9.5 to 10 runs into trouble when the rebuild script tries to apt-get the postgres 9.5 packages. I worked around it by backing up the previous version, moving /var/discourse/shared out of the way and redeploying a blank discourse to restore to. It seems like as long as you do a restore from backup it doesn’t have to download any ubuntu packages to convert the database.

Maybe there’s a way to point it to cached local .deb files for the various postgres versions but in our case clearing the old DB and restoring from backup was simpler.

---

<div class="post-metadata">

### Author: ![nil4](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nil4/32/81796_2.png) [@nil4](https://meta.discourse.org/u/nil4)
#### Post date: [June 9, 2018, 6:03pm UTC](https://meta.discourse.org/t/install-discourse-on-an-isolated-centos-7-server/73538/7 "2018-06-09T18:03:36Z")

</div>

@ssvenn you are spot on all the changes, particularly the command to copy the Ruby gems, thanks! ❤

It wasn’t clear to me which Git command was giving you trouble (where you had to move `git config` to execute earlier on). The only thing that I ran into, at the time, was the attempt to `git pull` to update pups, but that is in the launcher script. Anyway, happy to hear you found a way around it!

I tried to edit the OP with your suggestions but it looks like I don’t have permission, unfortunately.

When I upgraded Postgres to v10, I had to use some ugly tricks; downloading apt packages offline for both v9.5 and v10, and drop them in the apt-cache folder just before the commands to install them would run 🤕

Glad I got past that hurdle, and happy to see you’ve found (and shared!) your solution!

---

<div class="post-metadata">

### Author: ![malec](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/malec/32/138520_2.png) [@malec](https://meta.discourse.org/u/malec)
#### Post date: [April 19, 2019, 3:43pm UTC](https://meta.discourse.org/t/install-discourse-on-an-isolated-centos-7-server/73538/8 "2019-04-19T15:43:05Z")

</div>

Hi,

This topic is the one and only reason I was able to deploy discourse in my environment. I am very grateful for the info provided here.

However I tried updating to the latest version and it seems a new dependency was added and it tries to pull from [geolite.maxmind.com](http://geolite.maxmind.com) and this causes the rebuild to fail (using HEAD – If I try to use tests-passed I get another error that might not be related.)

If anyone has any idea on how to fix this, i’d love to be able to continue using discourse.

On the other hand, I think it’d be great if the discourse team could provide us with some form of offline installer for the major versions, it doesn’t seem it would be too complicated to create a pipeline to bundle all the assets and adapt the install script for offline install.

Thanks anyway to everyone involved in this project.

---

<div class="post-metadata">

### Author: ![codinghorror](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/codinghorror/32/110067_2.png) [@codinghorror](https://meta.discourse.org/u/codinghorror)
#### Post date: [April 19, 2019, 3:57pm UTC](https://meta.discourse.org/t/install-discourse-on-an-isolated-centos-7-server/73538/9 "2019-04-19T15:57:53Z")

</div>

Yes, we should provide some workaround. This is for the geolocation of IP addresses to show detailed login history to all users, and proactively alert if admins are logging in from suspicious locations. Any ideas @sam or @nbianca ?

---

<div class="post-metadata">

### Author: ![ssvenn](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ssvenn/32/86740_2.png) [@ssvenn](https://meta.discourse.org/u/ssvenn)
#### Post date: [April 23, 2019, 9:51am UTC](https://meta.discourse.org/t/install-discourse-on-an-isolated-centos-7-server/73538/10 "2019-04-23T09:51:42Z")

</div>

some sort of official --create-cache and --use-cache flags in the launcher script would be great, but I think isolated networks is kind of an edge case.

we can probably work around this issue by messing with /etc/hosts in the container and point [geolite.maxmind.com](http://geolite.maxmind.com) to the IP of an internal webserver, I’ll play around with it in my lab environment.

---

<div class="post-metadata">

### Author: ![malec](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/malec/32/138520_2.png) [@malec](https://meta.discourse.org/u/malec)
#### Post date: [April 23, 2019, 4:41pm UTC](https://meta.discourse.org/t/install-discourse-on-an-isolated-centos-7-server/73538/11 "2019-04-23T16:41:25Z")

</div>

> [@ssvenn](#):
>
> we can probably work around this issue by messing with /etc/hosts in the container and point [geolite.maxmind.com](http://geolite.maxmind.com) to the IP of an internal webserver, I’ll play around with it in my lab environment.

Thought about this and realized it would make handling SSL verification very complex, but I don’t know much about SSL so I might be wrong on this one 😉

I decided to circumvent the problem by hosting the two required files `GeoLite2-City` and `GeoLite2-ASN` on our internal software repository and modifying `lib/discourse_ip_info.rb ` line 27 (discourse.git)

```ruby
      uri = URI("https://geolite.maxmind.com/download/geoip/database/#{name}.tar.gz")

```

Changed it to our internal software repository URL and it worked fine (if you are using HTTPS you will either have to inject your certificate chain and use `update-ca-trust` OR create an unsecured SSL context)

---

<div class="post-metadata">

### Author: ![malec](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/malec/32/138520_2.png) [@malec](https://meta.discourse.org/u/malec)
#### Post date: [April 23, 2019, 4:48pm UTC](https://meta.discourse.org/t/install-discourse-on-an-isolated-centos-7-server/73538/12 "2019-04-23T16:48:19Z")

</div>

Creating a separate post to discuss this issue (maybe this should be split in another topic entirely for clarity?)

> [@ssvenn](#):
>
> some sort of official --create-cache and --use-cache flags in the launcher script would be great

100 % this.

> [@ssvenn](#):
>
> but I think isolated networks is kind of an edge case.

I would tend to disagree with this. Lots of industries have isolated networks for security reasons, be it banking, energy, health & medicine…

Is it an edge case for the current population of Discourse users ? yes, definitely  
But maybe it’s an untapped market for Discourse that could further expand the userbase and bring feedback & improvements (I know my Discourse instance is likely to receive a stringent security audit in the near future, I will report everything that can be safely disclosed).

I hope we can hear from @codinghorror and the rest of the team on this issue.

Again, I would like to thank everyone involved and I am very glad I was able to bring back my discourse online (rollback to previous app container was impossible in my situation due to my own stupidity).

---

<div class="post-metadata">

### Author: ![ssvenn](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ssvenn/32/86740_2.png) [@ssvenn](https://meta.discourse.org/u/ssvenn)
#### Post date: [April 23, 2019, 6:31pm UTC](https://meta.discourse.org/t/install-discourse-on-an-isolated-centos-7-server/73538/13 "2019-04-23T18:31:44Z")

</div>

Yeah I agree there’s definitely an untapped market for enterprises wanting to use it for collaboration on firewalled corporate networks. It is fairly easy to get really slick integration with Active Directory and internal Exchange email in a Windows domain.

[https://meta.discourse.org/t/active-directory-sso-aka-integrated-windows-login/26548?u=ssvenn](https://meta.discourse.org/t/active-directory-sso-aka-integrated-windows-login/26548)

> [@Configure direct-delivery incoming email for self-hosted sites with Mail-Receiver](https://meta.discourse.org/t/straightforward-direct-delivery-incoming-mail/49487):
>
> Discourse is all about enabling civilized discussion. While plenty of people like a web interface, e-mail is still the “hub” of many people’s online lives. That’s why sending e-mail is so important, and when you’re sending e-mail, you really want to be able to receive it, too. There are several reasons why: If e-mails “bounce” (they can’t be delivered for some reason), you need to know about that. Repeatedly sending e-mails that bounce will get your e-mails flagged as spam. Receiving e-ma…

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [April 23, 2019, 7:43pm UTC](https://meta.discourse.org/t/install-discourse-on-an-isolated-centos-7-server/73538/14 "2019-04-23T19:43:36Z")

</div>

> [@ssvenn](#):
>
> I agree there’s definitely an untapped market for enterprises wanting to use it for collaboration on firewalled corporate networks.

As a full-time Discourse consultant, I am always on the lookout for “untapped markets.” I have a bit for work for corporate environments, but in my experience, people who have firewalled corporate networks won’t let anyone on their firewalled corporate network to help them do the work.

I have suffered through some fairly painful screen shares. . . and a fair amount of “OK, now what do you see after you typed `./launcher rebuild web_only`”

If anyone is interested, I can help create Ansible playbooks to deploy Discourse, which might allow for testing on non-firewalled networks that could then be deployed internally. I keep thinking that I’ll have a Kubernetes installation available as a service Real Soon Now.

---

<div class="post-metadata">

### Author: ![nil4](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nil4/32/81796_2.png) [@nil4](https://meta.discourse.org/u/nil4)
#### Post date: [May 11, 2019, 12:03pm UTC](https://meta.discourse.org/t/install-discourse-on-an-isolated-centos-7-server/73538/15 "2019-05-11T12:03:25Z")

</div>

> [@malec](#):
>
> However I tried updating to the latest version and it seems a new dependency was added and it tries to pull from [geolite.maxmind.com](http://geolite.maxmind.com) and this causes the rebuild to fail (using HEAD – If I try to use tests-passed I get another error that might not be related.)

@malec today I ran into the same issue, and managed to find a way around it, but as usual it wasn’t pretty.

It looks like the rake task added by @nbianca in [PR #7340](https://github.com/discourse/discourse/pull/7340) checks the modification date on the GeoLite files included in the Discourse base image, and if they’re older than **2 days** , will attempt to download them again during bootstrap; see [the relevant code here](https://github.com/nbianca/discourse/blob/aceabe4e4434078d3b4460b2b2b33ae87bebb5fc/lib/tasks/assets.rake#L170-L172).

The added task could arguably handle failure more gracefully, e.g. by printing a warning and failing back to using the already-present files, but right now it just fails bootstrap.

So here is what I did, hoping it helps you and anyone else stuck with this:

Download the `GeoLite2-ASN.mmdb` and `GeoLite2-City.mmdb` files and store them on your Discourse host; I put them under `/root/local/maxmind.com`.

Map this folder as a Docker volume in your `app.yml` file, e.g via:

```yaml
    - volume:
      host: /root/local/maxmind.com
      guest: /local-maxmind.com

```

Add a `bundle_exec` hook to your `app.yml` file, to be run as early as possible:

```yaml
run:
  - exec:
      cd: $home
      hook: bundle_exec
      cmd:
        - mkdir -p $home/vendor/data
        - ls -la $home/vendor/data
        - cp -rv /local-maxmind.com/*.mmdb $home/vendor/data/
        - ls -la $home/vendor/data

```

This copies the GeoLite files from your host, overwriting the ones already present in the Discourse base image.

You can verify in the bootstrap log, using the output of the two `ls -la` statements, whether the files have been overwritten. The first `ls -la` output will look something like:

```plaintext
I, [2019-05-11T11:06:39.528299 #6] INFO -- : > cd /var/www/discourse && ls -la /var/www/discourse/vendor/data
I, [2019-05-11T11:06:39.533286 #6] INFO -- : total 65948
-rw-r--r-- 1 root root 6473392 Apr 29 10:37 GeoLite2-ASN.mmdb
-rw-r--r-- 1 root root 61106856 Apr 29 10:37 GeoLite2-City.mmdb

```

Note that the modification time is Apr 29, i.e. older than 2 days. The rake task would attempt to download these files again.

After overwriting the files, the second `ls -la` output will instead look something like this:

```plaintext
I, [2019-05-11T11:06:39.533336 #6] INFO -- : > cd /var/www/discourse && cp -rv /local-maxmind.com/*.mmdb /var/www/discourse/vendor/data/
I, [2019-05-11T11:06:39.604593 #6] INFO -- : '/local-maxmind.com/GeoLite2-ASN.mmdb' -> '/var/www/discourse/vendor/data/GeoLite2-ASN.mmdb'
'/local-maxmind.com/GeoLite2-City.mmdb' -> '/var/www/discourse/vendor/data/GeoLite2-City.mmdb'

I, [2019-05-11T11:06:39.604695 #6] INFO -- : > cd /var/www/discourse && ls -la /var/www/discourse/vendor/data
I, [2019-05-11T11:06:39.608645 #6] INFO -- : total 66028
-rw-r--r-- 1 2000 2000 6492486 May 11 10:52 GeoLite2-ASN.mmdb
-rw-r--r-- 1 2000 2000 61030828 May 11 10:52 GeoLite2-City.mmdb

```

The `mmdb` files are now up-to-date as far as the rake tasks are concerned. This will allow bootstrap to carry on without trying to download them.

Additionally, I also added an environment variable in my `app.yml` file:

```yaml
env:
  DISCOURSE_REFRESH_MAXMIND_DB_DURING_PRECOMPILE_DAYS: 3650

```

I was trying to override the [default setting of 2 days](https://github.com/nbianca/discourse/blob/aceabe4e4434078d3b4460b2b2b33ae87bebb5fc/config/site_settings.yml#L1484) for GeoLite checks, but this appeared to not have any effect in my testing. Your mileage may vary.

* * *

/cc @sam@nbianca @codinghorror – a better (or at least more graceful) way to handle GeoLite updates, or the ability to disable this during bootstrap would be greatly appreciated. Both GeoLite files are already present in the Discourse base image, and for some use cases (mine is on-premise use in an isolated network environment), fresh copies are really not essential.

It would be _really good_ to have an opt-in bootstrap option to just use the files embedded in the base image, without downloading. Or at least to not fail bootstrap when the GeoLite download fails; printing a warning and continuing with the files in the base image would be, in my mind, better than the current experience.

---

<div class="post-metadata">

### Author: ![Stephen](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/stephen/32/95011_2.png) [@Stephen](https://meta.discourse.org/u/Stephen)
#### Post date: [May 11, 2019, 12:48pm UTC](https://meta.discourse.org/t/install-discourse-on-an-isolated-centos-7-server/73538/16 "2019-05-11T12:48:51Z")

</div>

If the only thing being checked is the modification time couldn’t you just bump that using `touch`?

> [@nil4](#):
>
> Additionally, I also added an environment variable in my `app.yml` file:
> 
> ```plaintext
> env:
> DISCOURSE_REFRESH_MAXMIND_DB_DURING_PRECOMPILE_DAYS: 3650
> 
> ```
> 
> I was trying to override the [default setting of 2 days](https://github.com/nbianca/discourse/blob/aceabe4e4434078d3b4460b2b2b33ae87bebb5fc/config/site_settings.yml#L1484) for GeoLite checks, but this appeared to not have any effect in my testing. Your mileage may vary.

From the site\_settings.yml:

```
refresh_maxmind_db_during_precompile_days:
min: 0
max: 120
default: 2
hidden: true

```

So:

```
bundle exec rails c
SiteSetting.refresh_maxmind_db_during_precompile_days = 120

```

You can’t set it beyond the limit defined in the file you linked, but you can at least push it to four months.

---

<div class="post-metadata">

### Author: ![nil4](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nil4/32/81796_2.png) [@nil4](https://meta.discourse.org/u/nil4)
#### Post date: [May 11, 2019, 1:11pm UTC](https://meta.discourse.org/t/install-discourse-on-an-isolated-centos-7-server/73538/17 "2019-05-11T13:11:50Z")

</div>

@Stephen you’re absolutely right on both accounts, thanks a lot! This is a way cleaner solution – and much appreciated!

Using `touch` to update the GeoLite file mtime on every bootstrap works, of course.  
I also set `DISCOURSE_REFRESH_MAXMIND_DB_DURING_PRECOMPILE_DAYS` to 120 just in case the logic changes. (I don’t know how I missed the max value earlier!)

---

<div class="post-metadata">

### Author: ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### Post date: [May 13, 2019, 12:00am UTC](https://meta.discourse.org/t/install-discourse-on-an-isolated-centos-7-server/73538/18 "2019-05-13T00:00:18Z")

</div>

> [@nil4](#):
>
> Additionally, I also added an environment variable in my `app.yml` file:
> 
> ```plaintext
> env:
> DISCOURSE_REFRESH_MAXMIND_DB_DURING_PRECOMPILE_DAYS: 3650
> 
> ```

Yeah, we were missing a shadow by global option there, fixed now, you can just use that simple env change instead of the giant hack here.

[https://github.com/discourse/discourse/commit/4e1f25197da2b6e39e6f003f1c1229037486462c](https://github.com/discourse/discourse/commit/4e1f25197da2b6e39e6f003f1c1229037486462c)

---

<div class="post-metadata">

### Author: ![nil4](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nil4/32/81796_2.png) [@nil4](https://meta.discourse.org/u/nil4)
#### Post date: [May 13, 2019, 7:23pm UTC](https://meta.discourse.org/t/install-discourse-on-an-isolated-centos-7-server/73538/19 "2019-05-13T19:23:08Z")

</div>

Thank you @sam, much appreciated!

---

<div class="post-metadata">

### Author: ![ssvenn](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ssvenn/32/86740_2.png) [@ssvenn](https://meta.discourse.org/u/ssvenn)
#### Post date: [August 1, 2019, 1:26pm UTC](https://meta.discourse.org/t/install-discourse-on-an-isolated-centos-7-server/73538/20 "2019-08-01T13:26:40Z")

</div>

It seems like some plugins at some point started requiring more workarounds to be installable on the isolated server, when trying to build with `- git clone https://github.com/discourse/discourse-prometheus.git` or `- git clone https://github.com/discourse/discourse-calendar.git` i get

```plaintext

I, [2019-08-01T13:23:05.482497 #6] INFO -- : > cd /var/www/discourse && su discourse -c 'bundle exec rake db:migrate'
ERROR: While executing gem ... (TypeError)
    no implicit conversion of nil into String
I, [2019-08-01T13:24:10.583829 #6] INFO -- : gem install prometheus_exporter -v 0.4.13 -i /var/www/discourse/plugins/discourse-prometheus/gems/2.6.3 --no-document --ignore-dependencies --no-user-install

You are specifying the gem prometheus_exporter in /var/www/discourse/plugins/discourse-prometheus/plugin.rb, however it does not exist!
Looked for: /var/www/discourse/plugins/discourse-prometheus/gems/2.6.3/specifications/prometheus_exporter-0.4.13.gemspec

```

and

```plaintext
I, [2019-08-01T13:15:56.607026 #6] INFO -- : > cd /var/www/discourse && su discourse -c 'bundle exec rake db:migrate'
ERROR: While executing gem ... (TypeError)
    no implicit conversion of nil into String
I, [2019-08-01T13:17:01.618404 #6] INFO -- : gem install holidays -v 7.1.0 -i /var/www/discourse/plugins/discourse-calendar/gems/2.6.3 --no-document --ignore-dependencies --no-user-install

You are specifying the gem holidays in /var/www/discourse/plugins/discourse-calendar/plugin.rb, however it does not exist!
Looked for: /var/www/discourse/plugins/discourse-calendar/gems/2.6.3/specifications/holidays-7.1.0.gemspec

```

I haven’t found a way to get around this yet, for now I’ve just disabled the ones that cause rebuild errors.

[Next page](https://meta.discourse.org/t/install-discourse-on-an-isolated-centos-7-server/73538.md?page=2)
