summaryrefslogtreecommitdiff
path: root/doc/INSTALL.md
blob: 8056f7cf7345a9966b5b16bf9f375e17631e143e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
# CCCMS Installation Guide

This document covers the non-obvious steps required to install the CCCMS
stack on a fresh FreeBSD jail. It assumes a FreeBSD 14.x base jail with
network access and a working pkg repository.

## 1. Install packages

```sh
pkg install gmake pkgconf curl gnupg git autoconf automake libtool bash \
  readline libyaml libffi gdbm libxml2 libxslt libical \
  postgresql16-server postgresql16-client \
  ImageMagick7-nox11 node vim
```

Note: the package is `ImageMagick7-nox11`, not `ImageMagick-nox11`. The
nox11 variant avoids pulling in the entire X11 dependency chain.

## 2. Enable sysvipc for the jail

PostgreSQL uses System V shared memory for inter-process communication.
On the host, the jail must have sysvipc enabled. In `/etc/jail.conf` or
the jail's ezjail configuration:

  `allow.sysvipc = 1;`

Restart the jail after making this change. Without it, PostgreSQL will
fail to start with a shared memory error.

## 3. Enable and initialise PostgreSQL

```sh
# Enable PostgreSQL in rc.conf
echo 'postgresql_enable="YES"' >> /etc/rc.conf

# Initialise the database cluster
service postgresql initdb

# Start PostgreSQL
service postgresql start
```

## 4. Create database roles and set permissions

```sh
psql -U postgres postgres
```

```sql
CREATE ROLE rails WITH LOGIN PASSWORD 'your-password-here';
ALTER ROLE rails CREATEDB;
```

`CREATEDB` is required for the Rails test suite to create and drop the
test database between runs.

## 5. Create databases

```sql
CREATE DATABASE cccms_production OWNER rails ENCODING 'UTF8'
  LC_COLLATE 'en_US.UTF-8' LC_CTYPE 'en_US.UTF-8' TEMPLATE template0;
CREATE DATABASE cccms_dev OWNER rails ENCODING 'UTF8'
  LC_COLLATE 'en_US.UTF-8' LC_CTYPE 'en_US.UTF-8' TEMPLATE template0;
CREATE DATABASE psql_test OWNER rails ENCODING 'UTF8'
  LC_COLLATE 'en_US.UTF-8' LC_CTYPE 'en_US.UTF-8' TEMPLATE template0;
```

`TEMPLATE template0` is required when specifying a non-default locale.

## 6. Restore the database dump (or start empty)

If restoring from a pg_dump:

```sh
pg_restore -U postgres -d cccms_production \
  --no-owner --no-acl /path/to/cccms_production.dump

pg_restore -U postgres -d cccms_dev \
  --no-owner --no-acl /path/to/cccms_production.dump
```

Expected harmless warnings:
- `schema "public" already exists` — benign, ignore
- `array_accum aggregate` failure — dead code, ignore

Transfer ownership to the rails user (REASSIGN OWNED does not work on
PostgreSQL 15+ due to system object protection):

```sh
psql -U postgres cccms_production
```

```sql
DO $$
DECLARE
  obj RECORD;
BEGIN
  FOR obj IN
    SELECT tablename FROM pg_tables WHERE schemaname = 'public'
  LOOP
    EXECUTE 'ALTER TABLE public.' || quote_ident(obj.tablename) ||
            ' OWNER TO rails';
  END LOOP;
  FOR obj IN
    SELECT sequence_name FROM information_schema.sequences
    WHERE sequence_schema = 'public'
  LOOP
    EXECUTE 'ALTER SEQUENCE public.' || quote_ident(obj.sequence_name) ||
            ' OWNER TO rails';
  END LOOP;
  FOR obj IN
    SELECT viewname FROM pg_views WHERE schemaname = 'public'
  LOOP
    EXECUTE 'ALTER VIEW public.' || quote_ident(obj.viewname) ||
            ' OWNER TO rails';
  END LOOP;
END $$;

ALTER SCHEMA public OWNER TO rails;
```

Repeat for `cccms_dev`.

## 7. Clone the repository

```sh
cd /usr/local/www
git clone https://github.com/erdgeist/cccms.git
cd cccms
git checkout rails-upgrade
```

## 8. Copy assets (optional but recommended)

The `public/system/uploads/` directory contains all uploaded files
referenced by the database. Without it, images and attachments will be
missing throughout the site.

```sh
# On the source system:
tar -czf /tmp/cccms_uploads.tar.gz -C /usr/local/www cccms/public/system

# On the new system:
tar -xzf /path/to/cccms_uploads.tar.gz -C /usr/local/www
```

## 9. Copy gitignored config files

These files are not in the repository and must be copied or created:

```sh
# Required:
config/database.yml
config/initializers/secret_token.rb

# If used:
config/initializers/exception_notification.rb
/usr/local/etc/unicorn.rb
```

`database.yml` template:

```yaml
development:
  adapter: postgresql
  encoding: unicode
  database: cccms_dev
  pool: 5
  username: rails
  password: your-password-here

test:
  adapter: postgresql
  encoding: UTF8
  database: psql_test
  username: rails
  password:

production:
  adapter: postgresql
  encoding: unicode
  database: cccms_production
  pool: 5
  username: rails
  password: your-password-here
```

## 10. Install rvm

rvm 1.29.12 is the latest formal release as of mid-2026. Download and
verify before installing:

```sh
curl -L https://github.com/rvm/rvm/releases/download/1.29.12/1.29.12.tar.gz \
  -o /tmp/rvm-1.29.12.tar.gz
curl -L https://github.com/rvm/rvm/releases/download/1.29.12/1.29.12.tar.gz.asc \
  -o /tmp/rvm-1.29.12.tar.gz.asc

gpg --keyserver hkps://keys.openpgp.org \
  --recv-keys 7D2BAF1CF37B13E2069D6956105BD0E739499BDB

gpg --verify /tmp/rvm-1.29.12.tar.gz.asc /tmp/rvm-1.29.12.tar.gz
```

If verification passes:

```sh
tar -xzf /tmp/rvm-1.29.12.tar.gz -C /tmp
bash /tmp/rvm-1.29.12/install --auto-dotfiles
source /usr/local/rvm/scripts/rvm
```

The installed rvm ships with a stale known-versions list that only goes
to Ruby 3.0.0. Update it immediately:

```sh
curl -L https://raw.githubusercontent.com/rvm/rvm/master/config/known \
  -o /usr/local/rvm/config/known
rvm list known | grep '^\[ruby-\]3\.'
```

Should now show Ruby 3.2.x and later.

## 11. Install Ruby and create gemset

```sh
source /usr/local/rvm/scripts/rvm
rvm install 3.2.11 --autolibs=read-only --with-opt-dir=/usr/local
rvm use 3.2.11
rvm gemset create rails7-upgrade
rvm use 3.2.11@rails7-upgrade
```

The `.ruby-version` and `.ruby-gemset` files in the project root will
cause rvm to switch automatically when entering the project directory.

## 12. Install bundler and gems

```sh
gem install bundler
cd /usr/local/www/cccms
export MAKE=gmake
bundle install 2>&1 | tee /tmp/bundle_install.log
```

`MAKE=gmake` is required because FreeBSD's native make (BSD make) uses
different `-j` syntax than native gems expect. Without it, several native
gem compilations will fail.

## 13. Run migrations

```sh
bundle exec rails db:migrate
```

If restoring an existing database, first insert fake migration versions
to prevent re-running migrations that were applied to the old schema:

```sql
INSERT INTO schema_migrations (version) VALUES
  ('20260624035149'), ('20260624035150'), ('20260624035151'),
  ('20260624035152'), ('20260624035153'),
  ('20260625031409')
ON CONFLICT DO NOTHING;
```

Then run `db:migrate` to apply only new migrations.

To enable full-text search (requires PostgreSQL 10+ with plpgsql):

```sh
mv doc/20260626025705_add_search_vector_to_page_translations.rb.pending \
   db/migrate/20260626025705_add_search_vector_to_page_translations.rb
bundle exec rails db:migrate
```

## 14. Compile admin assets

```sh
bundle exec rails assets:precompile
```

This compiles the admin JavaScript bundle (jQuery, jQuery UI, hotkeys)
into `public/assets/`. Required for the admin interface to work. Must be
re-run after any changes to `app/assets/javascripts/admin_bundle.js`.

## 15. Run tests (optional but recommended)

```sh
bundle exec rake test
```

Expected result: 129 runs, ~339 assertions, 3 failures, 0 errors.
The 3 failures are pre-existing and documented in the handover document.

## 16. Start the server

Development:

```sh
bundle exec rails server -p 3000 -b 0.0.0.0 -e development
```

Note: `-b 0.0.0.0` is required — `localhost` does not resolve inside
a FreeBSD jail.

Production (unicorn):

```sh
/usr/local/rvm/gems/ruby-3.2.11@rails7-upgrade/wrappers/unicorn \
  -c /usr/local/etc/unicorn.rb -E production -D
```

The rc.d script at `/etc/rc.d/cccms` needs updating from `unicorn_rails`
to `unicorn` before use — see the handover document for details.

## Known Gotchas

**sysvipc:** PostgreSQL will fail silently or with a cryptic error if
sysvipc is not enabled for the jail. Enable it on the host before starting
PostgreSQL.

**MAKE=gmake:** Native gem compilation fails without this. Set it before
every `bundle install` or add to your shell profile.

**rvm known versions:** rvm 1.29.12 ships with a stale `config/known` that
only lists Ruby up to 3.0.0. Always update from master after installing rvm.

**ImageMagick 7:** The `convert` command is deprecated; use `magick convert`.
The `file_attachment.rb` concern needs updating before production use.

**pg_hba.conf:** The default FreeBSD PostgreSQL configuration uses `trust`
for local Unix socket connections, which is sufficient for the application.
No changes needed unless TCP connections are required.

**assets:precompile:** Must be run after checkout and after any changes to
admin JavaScript. The compiled files in `public/assets/` are gitignored.

**chaos_calendar include path:** On FreeBSD 14.x with libical 3.0.20+,
the include path is `<libical/ical.h>` not `<ical.h>`. This is already
fixed in the `erdgeist-ruby1.9` branch.