Support #565
Updated by Daniel Curtis about 8 years ago
This guide is to document setting up a self-hosted HabitRPG node.
h2. Prepare the system
* Start by updating the system and ports tree:
<pre>
pkg update && pkg upgrade
portsnap fetch extract
</pre>
* Install a few dependencies:
<pre>
pkg install node4 bash git gettext-tools gmake mongodb portmaster bison autoconf nasm
</pre>
* Install npm from ports:
<pre>
portmaster www/npm
</pre>
*NOTE*: Make sure to enable *[X] NODE4* when configuring the @www/npm@ port.
* Install a few npm packages globally:
<pre>
npm install -g gulp grunt-cli bower phantomjs
</pre>
* Start and enable mongodb at boot:
<pre>
echo 'mongod_enable="YES"' >> /etc/rc.conf
service mongod start
</pre>
* Add the rpg user
<pre>
pw add user -n rpg -m -s /usr/local/bin/bash -c "HabitRPG"
</pre>
h2. Install HabitRPG
* Download the develop branch from GitHub:
<pre>
cd /usr/local/www
git clone -b develop https://github.com/HabitRPG/habitrpg.git
cd habitrpg
</pre>
* Set the NPM registry:
<pre>
npm config set registry "http://registry.npmjs.org/"
</pre>
* Install the npm and bower packages:
<pre>
npm install
</pre>
* Create a config file from the example one:
<pre>
cp config.json.example config.json
</pre>
* Edit @config.json@ with your values for:
*# *ADMIN_EMAIL*
*# *SMTP_USER*
*# *SMTP_PASS*
*# *SMTP_SERVICE*
* Change ownership of the habitrpg directory to the rpg user:
<pre>
chown -R rpg:rpg /usr/local/www/habitrpg
</pre>
* Switch to the rpg user:
<pre>
su - rpg
cd /usr/local/www/habitrpg
</pre>
* Then run bower update:
<pre>
bower update
</pre>
* Start the web application using NPM:
<pre>
npm start
</pre>
h2. HabitRPG Init Script
* Install pm2:
<pre>
npm install -g pm2
</pre>
* Create pm2 FreeBSD init script:
<pre>
vi /usr/local/etc/rc.d/habitrpg
</pre>
#* and add the following
<pre>
#!/bin/sh
# PROVIDE: habitrpg
# KEYWORD: shutdown
. /etc/rc.subr
name="habitrpg"
start_cmd="${name}_start"
stop_cmd="${name}_stop"
habitrpg_start() {
echo "habitrpg starting"
su - rpg -c "/usr/local/bin/pm2 start /usr/local/www/habitrpg/website/src/server.js; exit"
}
habitrpg_stop() {
echo "habitrpg stopping"
su - rpg -c "/usr/local/bin/pm2 kill; exit"
}
run_rc_command "$1"
</pre>
* And make it executable:
<pre>
chmod +x /usr/local/etc/rc.d/habitrpg
</pre>
* Start and enable pm2 at boot
<pre>
echo 'habitrpg_enable="YES"' >> /etc/rc.conf
service habitrpg start
</pre>
h2. Troubleshooting
I encountered a couple of errors while starting the web application.
h3. Failure to start grunt
> failed to locate @import file ../bower_components/angular-loading-bar/build/loading-bar.css Warning: Stylus failed to compile. Used --force, continuing.
You need to update bower and restart the command:
<pre>
bower update
grunt run:dev
</pre>
h3. bower update fails
> Error: EEXIST, rename '.bower-cache/ef2188def21eb1bbd1f1792311942a53/1.2.15-build.2360%2Bsha.6b18a56'
If you encounter this or a similar error when issuing a bower update, perform the following:
<pre>
cd .bower-cache/ef2188def21eb1bbd1f1792311942a53/
rm -rf 1.2.15-build.2360%2Bsha.6b18a56
</pre>
The actual names of these directories may differ on your system.
h3. Problem with OAuth client ID
I recently updated my self-hosted habitica and when I went to restart the app, it crashed complaining about:
<pre>
TypeError: OAuth2Strategy requires a clientID option
</pre>
I tracked this back to the Facebook and Google OAuth strategies. And since I use neither of those services, I decided to disable them entirely.
* Edit the passport setup library file:
<pre>
vi /usr/local/www/habitrpg/website/server/libs/setupPassport.js
</pre>
#* And comment out the parts that reference facebook and google:
<pre>
import passport from 'passport';
import nconf from 'nconf';
//import { Strategy as FacebookStrategy } from 'passport-facebook';
//import { Strategy as GoogleStrategy } from 'passport-google-oauth20';
// Passport session setup.
// To support persistent login sessions, Passport needs to be able to
// serialize users into and deserialize users out of the session. Typically,
// this will be as simple as storing the user ID when serializing, and finding
// the user by ID when deserializing. However, since this example does not
// have a database of user records, the complete Facebook profile is serialized
// and deserialized.
passport.serializeUser((user, done) => done(null, user));
passport.deserializeUser((obj, done) => done(null, obj));
// TODO remove?
// This auth strategy is no longer used. It's just kept around for auth.js#loginFacebook() (passport._strategies.facebook.userProfile)
// The proper fix would be to move to a general OAuth module simply to verify accessTokens
/*
passport.use(new FacebookStrategy({
clientID: nconf.get('FACEBOOK_KEY'),
clientSecret: nconf.get('FACEBOOK_SECRET'),
// callbackURL: nconf.get("BASE_URL") + "/auth/facebook/callback"
}, (accessToken, refreshToken, profile, done) => done(null, profile)));
passport.use(new GoogleStrategy({
clientID: nconf.get('GOOGLE_CLIENT_ID'),
clientSecret: nconf.get('GOOGLE_CLIENT_SECRET'),
}, (accessToken, refreshToken, profile, done) => done(null, profile)));
*/
</pre>
h2. Resources
* http://habitrpg.wikia.com/wiki/Setting_up_HabitRPG_locally
* http://habitrpg.wikia.com/wiki/Guidance_for_Blacksmiths#Git
* http://habitrpg.wikia.com/wiki/Installation_troubleshooting
* https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager
* https://github.com/ariya/phantomjs/issues/12963
* https://github.com/Unitech/pm2/issues/157