# How to script the setup wizard?

**URL:** https://meta.discourse.org/t/how-to-script-the-setup-wizard/169288
**Category:** Self-hosting
**Created:** [November 4, 2020, 10:21pm UTC](https://meta.discourse.org/t/how-to-script-the-setup-wizard/169288 "2020-11-04T22:21:14Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![dachary](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/dachary/32/119731_2.png) [@dachary](https://meta.discourse.org/u/dachary)
#### Post date: [November 4, 2020, 10:21pm UTC](https://meta.discourse.org/t/how-to-script-the-setup-wizard/169288/1 "2020-11-04T22:21:15Z")

</div>

Bonjour,

It sounds like it is a FAQ and I apologize in advance if it is: I apparently did not look hard enough 😊 How could I write a script to do the same as the wizard instead of doing it via the web interface ?

It would start with something that resembles [the Fabricate(admin) fixture](https://github.com/discourse/discourse/blob/master/spec/requests/application_controller_spec.rb#L7-L12) from the spec tests. And maybe called from [custom section of the container](https://github.com/discourse/discourse_docker/blob/master/samples/standalone.yml#L93-L99).

Thanks in advance for your help!

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [November 4, 2020, 11:17pm UTC](https://meta.discourse.org/t/how-to-script-the-setup-wizard/169288/2 "2020-11-04T23:17:34Z")

</div>

Wizard is half site settings, half API calls.

For API calls you can read [How to reverse engineer the Discourse API](https://meta.discourse.org/t/how-to-reverse-engineer-the-discourse-api/20576) and for site settings follow the example here:

> <https://github.com/discourse/discourse_docker/blob/master/samples/standalone.yml#L98>

---

<div class="post-metadata">

### Author: ![dachary](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/dachary/32/119731_2.png) [@dachary](https://meta.discourse.org/u/dachary)
#### Post date: [November 4, 2020, 11:19pm UTC](https://meta.discourse.org/t/how-to-script-the-setup-wizard/169288/3 "2020-11-04T23:19:41Z")

</div>

But … maybe that’s where I’m lost: in order for me to call the API I need an API key. And therefore an admin user… which I don’t have (yet). Is it possible to call the API without an API key ? Or to obtain an API key that would be detached from a user and have admin credentials ?

---

<div class="post-metadata">

### Author: ![dachary](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/dachary/32/119731_2.png) [@dachary](https://meta.discourse.org/u/dachary)
#### Post date: [November 5, 2020, 3:13pm UTC](https://meta.discourse.org/t/how-to-script-the-setup-wizard/169288/4 "2020-11-05T15:13:15Z")

</div>

It looks like I should use [rake:admin](https://meta.discourse.org/t/piping-into-rake-admin-create/73643) to create the admin user. Rather, I think the admin user is already created but not approved so I would need to change it so it is approved.

Or maybe I can create an API key with [api\_key:create\_master](https://github.com/discourse/discourse/blob/master/lib/tasks/api.rake#L4) and use it to create the admin user ?

```plaintext
root@forum:/var/www/discourse# RAILS_DB=secondsite rake 'api_key:create_master[MASTERKEY]'
ad676e7413778aaaaa5d315c35f188591ef0edb4a4d4b2d644b9247a88421cfa

```

But it looks like I don’t quite understand how this master key is supposed to be used because this does not work:

```plaintext
# curl -X GET "https://forum2/categories" -H "Accept: application/json" -H "Api-Key: ad676e7413778aa3a5d315c35f91ef0edb4a4d4b2d644b924b7a88421cfa"
{"errors":["You are not permitted to view the requested resource. The API username or key is invalid."],"error_type":"invalid_access"}

```

However, if I create an admin user:

```plaintext
root@forum:/var/www/discourse# RAILS_DB=secondsite rake 'admin:create' 
Email: loic@dachary.org
Password:  
Repeat password:  

Ensuring account is active!

Account created successfully with username loic
Do you want to grant Admin privileges to this account? (Y/n) Y

Your account now has Admin privileges!

```

and then use the same master key specifying the newly created user, it does work:

```plaintext
curl -X GET "https://forum2/categories" -H "Accept: application/json" -H "Api-Key: ad676e7413778aa3a5d315c358591ef0edb4a4d4b2d644b924b7a88421cfa" -H "Api-Username: loic"
{"category_list":{"can...

```

and has admin privileges since it can also access `/admin/site_settings/category/branding`

---

<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: [November 5, 2020, 3:30pm UTC](https://meta.discourse.org/t/how-to-script-the-setup-wizard/169288/5 "2020-11-05T15:30:25Z")

</div>

What are you trying to accomplish exactly? You want to automate creating an admin user and setting some settings?

---

<div class="post-metadata">

### Author: ![dachary](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/dachary/32/119731_2.png) [@dachary](https://meta.discourse.org/u/dachary)
#### Post date: [November 5, 2020, 3:32pm UTC](https://meta.discourse.org/t/how-to-script-the-setup-wizard/169288/6 "2020-11-05T15:32:39Z")

</div>

Yes, exactly. I want to create a new forum from scratch and populate it with users and categories and topics, from a script that does not require any browser interaction.

---

<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: [November 5, 2020, 3:33pm UTC](https://meta.discourse.org/t/how-to-script-the-setup-wizard/169288/7 "2020-11-05T15:33:39Z")

</div>

Perhaps just create that database first and restore it as part of the installe process?

---

<div class="post-metadata">

### Author: ![dachary](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/dachary/32/119731_2.png) [@dachary](https://meta.discourse.org/u/dachary)
#### Post date: [November 5, 2020, 3:34pm UTC](https://meta.discourse.org/t/how-to-script-the-setup-wizard/169288/8 "2020-11-05T15:34:38Z")

</div>

I don’t have any database: the users, categories and topics will be created using data from mailman2.

---

<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: [November 5, 2020, 3:35pm UTC](https://meta.discourse.org/t/how-to-script-the-setup-wizard/169288/9 "2020-11-05T15:35:38Z")

</div>

If you want to import the data, just do that as a separate process.

---

<div class="post-metadata">

### Author: ![dachary](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/dachary/32/119731_2.png) [@dachary](https://meta.discourse.org/u/dachary)
#### Post date: [November 5, 2020, 3:37pm UTC](https://meta.discourse.org/t/how-to-script-the-setup-wizard/169288/10 "2020-11-05T15:37:40Z")

</div>

If that was a one shot, that would be ok. But I want to be able to test the import script. And in order for the test to run, it must first create a discourse from scratch. Without requiring some sort of manual intervention in the middle of the automated test 😉

---

<div class="post-metadata">

### Author: ![dachary](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/dachary/32/119731_2.png) [@dachary](https://meta.discourse.org/u/dachary)
#### Post date: [November 5, 2020, 3:42pm UTC](https://meta.discourse.org/t/how-to-script-the-setup-wizard/169288/11 "2020-11-05T15:42:08Z")

</div>

For context, this is part of [the work I’m doing to import mailman2 into discourse](https://meta.discourse.org/t/working-on-a-mailman2-to-discourse-migration-script/169220). The test would run from tox which would:

- create a new discourse instance
- run various tests
- destroy the discourse instance

---

<div class="post-metadata">

### Author: ![dachary](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/dachary/32/119731_2.png) [@dachary](https://meta.discourse.org/u/dachary)
#### Post date: [November 5, 2020, 4:08pm UTC](https://meta.discourse.org/t/how-to-script-the-setup-wizard/169288/12 "2020-11-05T16:08:42Z")

</div>

Assuming a multisite installation, creating an approved admin user and an admin API key can be done with:

- `docker exec app env RAILS_DB=secondsite rake 'api_key:create_master[MYKEY]'`
- `( echo user1@example.com ; echo $pass ; echo $pass ; echo ) | docker exec -i app env RAILS_DB=secondsite rake 'admin:create'`

**Note** : if not on a multisite installation, just remove `env RAILS_DB=secondsite`

And then verify that it works with

```plaintext
curl -X GET https://forum2/admin/backups -H "Accept: application/json" -H "Api-Key: 886171a73dd12759b5d6c1915b0f0d4475e8b3fff3d97954b95171200b6" -H "Api-Username: user1"
[]

```

(special thanks to [Jay Pfaffman for the inspiration](https://meta.discourse.org/t/piping-into-rake-admin-create/73643))

After this is done, discourse no longer requires to run the wizard, although it shows that it should be run.

 ![d](https://global.discourse-cdn.com/meta/original/3X/0/1/019a87260cd7eed9c28c3473c7bab42a96c5e3d9.png)

---

<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: [November 5, 2020, 4:17pm UTC](https://meta.discourse.org/t/how-to-script-the-setup-wizard/169288/13 "2020-11-05T16:17:52Z")

</div>

I make a significant part of my living doing imports. I’m fairly certain that what I describe below is pretty much how everyone who does imports regularly does it.

What I would recommend is

- configure and run the importer
- test that it does what you want
- script re-running the importer to import the data that’s acquired since the first run
- test that
- run the final import when all of the above works.
- restore that data to your production server

The migration task and the setting up a production server task are totally different and have different requirements. Usually the migration task requires stuff that the production server does not (but I think that the mailmain importer is an exception).

Running a migration on a multisite server seems especially foolhardy.

---

<div class="post-metadata">

### Author: ![dachary](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/dachary/32/119731_2.png) [@dachary](https://meta.discourse.org/u/dachary)
#### Post date: [November 5, 2020, 4:25pm UTC](https://meta.discourse.org/t/how-to-script-the-setup-wizard/169288/14 "2020-11-05T16:25:34Z")

</div>

Thanks for the advice, I’ll follow this process. There is over 100GB worth of mbox archives, it will require at least a few tests.

> [@pfaffman](#):
>
> script re-running the importer to import the data that’s acquired since the first run

Regarding that… it looks like the mbox importer always creates a new category and is not able to use an existing one. Do you happen to know anything about this ?

> [@pfaffman](#):
>
> Running a migration on a multisite server seems especially foolhardy.

I did not know the meaning of [foolhardy](https://en.wiktionary.org/wiki/foolhardy): I like it and will reuse it 🙂

---

<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: [November 5, 2020, 4:33pm UTC](https://meta.discourse.org/t/how-to-script-the-setup-wizard/169288/15 "2020-11-05T16:33:25Z")

</div>

> [@dachary](#):
>
> There is over 100GB worth of mbox archives

All the more reason that re-running the import from scratch is a Bad Idea. That’s likely to take weeks. When you re-run the importer it imports only the new data (and I often modify it to entirely skip the old data).

You can probably modify the script to use an existing category by creating a CategoryCustomField. I’d recommend just starting with an empty database and letting the script create it, you can then customize it however you want and when you re-run the script it’ll continue to use it.

---

<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: [November 5, 2020, 4:36pm UTC](https://meta.discourse.org/t/how-to-script-the-setup-wizard/169288/16 "2020-11-05T16:36:29Z")

</div>

The real danger with your import is that there are likely to be differences in the data over the years, so stuff that works for 10 year old data won’t work for 5 year old and so on. But maybe you’ll be lucky.

---

<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: [November 6, 2020, 3:07pm UTC](https://meta.discourse.org/t/how-to-script-the-setup-wizard/169288/17 "2020-11-06T15:07:45Z")

</div>

> [@dachary](#):
>
> I did not know the meaning of [foolhardy](https://en.wiktionary.org/wiki/foolhardy): I like it and will reuse it 🙂

[Made me wonder…](https://books.google.com/ngrams/graph?content=Foolhardy&year_start=1800&year_end=2019&corpus=26&smoothing=3&direct_url=t1%3B%2CFoolhardy%3B%2Cc0)

---

<div class="post-metadata">

### Author: ![michaeld](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/michaeld/32/1594_2.png) [@michaeld](https://meta.discourse.org/u/michaeld)
#### Post date: [November 6, 2020, 6:50pm UTC](https://meta.discourse.org/t/how-to-script-the-setup-wizard/169288/18 "2020-11-06T18:50:05Z")

</div>

> [@pfaffman](#):
>
> Running a migration on a multisite server seems especially foolhardy.

Not sure if that’s a compliment 😉  
I always use multisite for imports. It allows for multiple forums to co-exist: one that I am tinkering with while the client can review the import at its neighbour. And it’s easy to copy a database to restart from a certain point.

---

<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: [November 6, 2020, 8:45pm UTC](https://meta.discourse.org/t/how-to-script-the-setup-wizard/169288/19 "2020-11-06T20:45:32Z")

</div>

> [@michaeld](#):
>
> Not sure if that’s a complim

Wait. . . what!?

> [@michaeld](#):
>
> I always use multisite for imports.

Well, knock me over with a feather! You’re pretty much the only person on the planet who doesn’t work for CDCK that I think knows more about imports than I do, and if you use multisite for imports then, well, I’ll consider doing the same. I generally crank up separate containers on the same host with traefik in front, so I guess it’s sort-of the same thing, but not really.

---

<div class="post-metadata">

### Author: ![system](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/system/32/443519_2.png) [@system](https://meta.discourse.org/u/system)
#### Post date: [December 6, 2020, 8:53pm UTC](https://meta.discourse.org/t/how-to-script-the-setup-wizard/169288/20 "2020-12-06T20:53:41Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
