https://wiki.archlinux.org/api.php?action=feedcontributions&user=Stbinan&feedformat=atomArchWiki - User contributions [en]2024-03-30T07:56:40ZUser contributionsMediaWiki 1.41.1https://wiki.archlinux.org/index.php?title=User_talk:Stbinan&diff=485914User talk:Stbinan2017-08-19T02:07:30Z<p>Stbinan: /* openrc */</p>
<hr />
<div>== openrc ==<br />
<br />
Hi, regarding [https://wiki.archlinux.org/index.php?title=OpenRC&type=revision&diff=485716&oldid=482491] could you add some more information on what "may not shutdown correctly" means and how it relates to [[ConsoleKit]]? Also, the information on {{ic|openrc-init}} is applicable to [[OpenRC#Installation]]. Thanks. -- [[User:Alad|Alad]] ([[User talk:Alad|talk]]) 16:44, 18 August 2017 (UTC)<br />
<br />
--- ---<br />
<br />
[[User:Alad|Alad]]: Hi, I have added detail for "may not shutdown correctly.<br />
ConsoleKit requires [https://aur.archlinux.org/packages/pm-utils/ pm-utils], which is used for suspend and hibernate power management. And it doesn't work with the openrc 0.28. {{ic|openrc-init}} is in the [https://aur.archlinux.org/packages/openrc-git/ openrc-git] package, so no necessary to add it to [[OpenRC#Installation]].</div>Stbinanhttps://wiki.archlinux.org/index.php?title=User_talk:Stbinan&diff=485913User talk:Stbinan2017-08-19T02:06:49Z<p>Stbinan: /* openrc */ Reply to Alad</p>
<hr />
<div>== openrc ==<br />
<br />
Hi, regarding [https://wiki.archlinux.org/index.php?title=OpenRC&type=revision&diff=485716&oldid=482491] could you add some more information on what "may not shutdown correctly" means and how it relates to [[ConsoleKit]]? Also, the information on {{ic|openrc-init}} is applicable to [[OpenRC#Installation]]. Thanks. -- [[User:Alad|Alad]] ([[User talk:Alad|talk]]) 16:44, 18 August 2017 (UTC)<br />
<br />
--- ---<br />
<br />
[[User:Alad|Alad]]: Hi, I have added detail for "may not shutdown correctly.<br />
ConsoleKit requires [https://aur.archlinux.org/packages/pm-utils/ pm-utils], which is used for suspend and hibernate power management. And it doesn't work with the openrc 0.28. {{ic|openrc-init} is in the [https://aur.archlinux.org/packages/openrc-git/ openrc-git] package, so no necessary to add it to [[OpenRC#Installation]].</div>Stbinanhttps://wiki.archlinux.org/index.php?title=OpenRC&diff=485912OpenRC2017-08-19T01:46:33Z<p>Stbinan: /* Using OpenRC with a desktop environment */ Add detail about shutdown problem.</p>
<hr />
<div>[[Category:Init]]<br />
[[ja:OpenRC]]<br />
[[ru:OpenRC]]<br />
{{Related articles start}}<br />
{{Related|init}}<br />
{{Related articles end}}<br />
{{Warning|Arch Linux only has official support for [[systemd]]. When using OpenRC, please mention so in support requests.}}<br />
<br />
[https://wiki.gentoo.org/wiki/OpenRC OpenRC] is a service manager maintained by the Gentoo developers. OpenRC is dependency based and works with the system provided init program, normally [[SysVinit]].<br />
<br />
== Installation ==<br />
<br />
{{Accuracy|{{AUR|openrc-sysvinit}} removes {{Pkg|systemd-sysvcompat}}}}<br />
<br />
OpenRC and accompanying packages are available in the [[AUR]]. For details on init components, see [[Init]].<br />
<br />
Install either the {{AUR|openrc}} or {{AUR|openrc-git}} package. {{AUR|openrc-sysvinit}} or {{Pkg|busybox}} are used as the init process. Service files are available from the {{AUR|openrc-arch-services-git}} package.<br />
<br />
To maintain compability with {{AUR|initscripts-fork}}, configuration files are installed to {{ic|'''/etc/openrc/'''}}. The sysvinit init binary is installed to {{ic|/usr/bin/init-openrc}} for compability with {{Pkg|systemd-sysvcompat}} or similar packages.<br />
<br />
=== Booting ===<br />
<br />
For booting with OpenRC add {{Ic|1=init=/usr/bin/init-openrc}} to the [[kernel parameters]]. To switch back to systemd, remove the parameter again.<br />
<br />
The {{Ic|1=/etc/openrc/conf.d}} directory, and the {{Ic|1=/etc/openrc/rc.d}} file is used for configuration.<br />
<br />
== Configuration ==<br />
<br />
For general information on configuring OpenRC, see:<br />
<br />
* [http://www.calculate-linux.org/main/en/openrc_manuals OpenRC manuals]<br />
* [http://www.gentoo.org/doc/en/openrc-migration.xml OpenRC migration]<br />
* [http://wiki.gentoo.org/wiki/OpenRC gentoo wiki]. <br />
<br />
For instructions when migrating from [[systemd]], see [[Init#Configuration]].<br />
<br />
=== Services ===<br />
<br />
OpenRC services are enabled by issuing {{ic|rc-update add ''service_name'' ''runlevel''}} as root. It is recommended to at least enable the following services:<br />
{| class="wikitable"<br />
! Service name<br />
! [https://wiki.gentoo.org/wiki/OpenRC#Named_runlevels Runlevel]<br />
! Description<br />
|-<br />
| udev<br />
| sysinit<br />
| Device hot-plugging<br />
|-<br />
| alsa<br />
| default<br />
| [[ALSA]] state<br />
|-<br />
| acpid<br />
| default<br />
| ACPI events<br />
|-<br />
| dbus<br />
| default<br />
| Messaging bus<br />
|-<br />
| dcron<br />
| default<br />
| Scheduling<br />
|-<br />
| syslog-ng<br />
| default<br />
| System logs<br />
|}<br />
<br />
See also [https://wiki.gentoo.org/wiki/Systemd#Native_services Native services] and [[Daemons]].<br />
<br />
=== Network ===<br />
<br />
The network is configured through {{ic|newnet}}. [https://github.com/funtoo/openrc/blob/master/README.newnet] Modify the {{ic|/etc/openrc/conf.d/network}} file; both the {{ic|ip}} ({{Pkg|iproute2}}) and the {{ic|ifconfig}} ({{Pkg|net-tools}}) commands are supported. Below is an example configuration using {{ic|ip}}.<br />
<br />
{{bc|<br />
<nowiki>ip_eth0="192.168.1.2/24"<br />
defaultiproute="via 192.168.1.1"<br />
ifup_eth0="ip link set \$int mtu 1500"<br />
</nowiki>}}<br />
<br />
The network service is added to the boot runlevel by default, so no further action is required. See [[Network configuration]] for general networking information.<br />
<br />
{{Note|1=You may also use [[NetworkManager]], [[dhcpcd]] or {{AUR|netcfg}} by enabling the respective services. ''netcfg'' mimics the [[netctl]] behaviour (see [https://bbs.archlinux.org/viewtopic.php?pid=1489283#p1489283] if you want to enable profiles connection on booting - requires {{ic|wpa_actiond}}). See [https://www.archlinux.org/netcfg/features.html netcfg features].}}<br />
<br />
=== Boot logs ===<br />
<br />
To enable boot logging, uncomment the {{ic|1=rc_logger="YES"}} line in {{ic|/etc/openrc/rc.conf}}. When enabled, boot logs are stored in {{ic|/var/log/rc.log}}.<br />
<br />
=== Hostname ===<br />
<br />
OpenRC sets the hostname from {{ic|/etc/openrc/conf.d/hostname}}. The file looks as follows:<br />
<br />
{{bc|# Set to the hostname of this machine<br />
hostname<nowiki>=</nowiki>"myhostname"}}<br />
<br />
=== Kernel modules ===<br />
<br />
OpenRC uses {{ic|/etc/openrc/conf.d/modules}} instead of {{ic|/etc/modules-load.d}}. For example:<br />
<br />
{{hc|/etc/openrc/conf.d/modules|2=<br />
# You should consult your kernel documentation and configuration<br />
# for a list of modules and their options.<br />
<br />
modules="vboxdrv acpi_cpufreq"<br />
}}<br />
<br />
=== Locale ===<br />
<br />
Keyboard layout can be configured via {{ic|/etc/openrc/conf.d/keymaps}} and {{ic|/etc/openrc/conf.d/consolefont}}. You can also configure the settings through the {{ic|/etc/locale.conf}} file, which is sourced via {{ic|/etc/profile.d/locale.sh}}. <br />
<br />
See [http://wiki.gentoo.org/wiki/Localization/HOWTO#Keyboard_layout_for_the_console] and [[Locale]] for details.<br />
<br />
== Usage ==<br />
<br />
This section draws a parallel between [[systemd]] and other [[init]] systems.<br />
<br />
You can omit the {{ic|.service}} and {{ic|.target}} extensions, especially if temporarily editing the [[kernel parameters]].<br />
<br />
{| class="wikitable" width="100%"<br />
! systemd !! SysVinit !! OpenRC !! Description<br />
|-<br />
| {{ic|systemctl list-units}} || {{ic|rc.d list}} || {{ic|rc-status}} || List running services status<br />
|-<br />
| {{ic|systemctl --failed}} || || {{ic|rc-status --crashed}} || Check failed services<br />
|-<br />
| {{ic|systemctl --all}} || || {{ic|rc-update -v show}} || Display all available services.<br />
|-<br />
| {{ic|systemctl (start, stop, restart, status) daemon.service}} || {{ic|rc.d (start, stop, restart) daemon}} || {{ic|rc-service (start, stop, restart, status) daemon}} || Change service state.<br />
|- <br />
| {{ic|systemctl (enable, disable) daemon.service}} || {{ic|chkconfig daemon (on, off)}} || {{ic|rc-update (add, del) daemon}} || Turn service on or off.<br />
|-<br />
| {{ic|systemctl daemon-reload}} || {{ic|chkconfig daemon --add}} || || Create or modify configuration.<br />
|}<br />
<br />
== Tips and tricks ==<br />
<br />
=== Quiet booting ===<br />
<br />
To hide boot messages from OpenRC, you can edit {{ic|/etc/inittab}} and add {{ic|--quiet}} to every openrc command. For further information check with {{ic|$ openrc -h}}.<br />
<br />
== Troubleshooting ==<br />
<br />
=== Error while unmounting /tmp ===<br />
<br />
When shutting the system down, you might get an error message such as <br />
<br />
{{bc|* Unmounting /tmp ... <br />
* in use but fuser finds nothing [ !! ]}}<br />
<br />
This can be fixed by adding<br />
<br />
no_umounts="/tmp"<br />
<br />
to {{ic|/etc/openrc/conf.d/localmount}}<br />
<br />
{{Note|This problem occurs only if your tmp is mounted as a tmpfs.}}<br />
<br />
=== Disabling IPv6 does not work ===<br />
<br />
One option is to add:<br />
<br />
# Disable ipv6<br />
net.ipv6.conf.all.disable_ipv6 = 1<br />
<br />
in a file with a {{ic|.conf}} extension under {{ic|/etc/openrc/sysctl.d}}<br />
<br />
=== During shutdown remounting root as read-only fails ===<br />
<br />
If the above happens, edit the {{ic|/etc/openrc/init.d/mount-ro}} file and put:<br />
<br />
telinit u<br />
<br />
after the following line:<br />
<br />
# Flush all pending disk writes now<br />
sync; sync<br />
<br />
=== /etc/sysctl.conf not found ===<br />
<br />
By default, {{ic|sysctl --system}} is called to load the sysctl configuration. [https://github.com/OpenRC/openrc/blob/master/init.d/sysctl.Linux.in#L17] This includes the {{ic|/etc/sysctl.conf}} file, which was removed from Arch. [https://www.archlinux.org/news/deprecation-of-etcsysctlconf/]<br />
<br />
To prevent a missing file error, create the file:<br />
<br />
# touch /etc/sysctl.conf<br />
<br />
=== opentmpfiles-setup failed to start ===<br />
<br />
On booting openrc you may see lines like these :<br />
<br />
* Setting up tmpfiles.d entries ...<br />
chattr: Operation not supported while setting flags on /var/log/journal<br />
chattr: No such file or directory while trying to stat /var/log/journal/%m<br />
chattr: Operation not supported while setting flags on /var/log/journal/remote<br />
[ !! ]<br />
ERROR: opentmpfiles-setup failed to start<br />
<br />
This is caused by {{ic|/usr/lib/tmpfiles.d/journal-nocow.conf}} using options that are only valid if journal is on a btrfs filesystem.<br />
<br />
See https://github.com/OpenRC/opentmpfiles/issues/2 for details<br />
<br />
A workaround is to create an empty /etc/tmpfiles.d/journal-nocow.conf to override the settings.<br />
<br />
== Using OpenRC with a desktop environment ==<br />
<br />
If using ''OpenRC'' with a [[desktop environment]], ConsoleKit may help. Install the [https://gist.github.com/ad73f9087f39d7cadd8e service] to {{ic|/etc/openrc/init.d}}, and enable it:<br />
<br />
# rc-update add consolekit default<br />
<br />
See [[ConsoleKit]] for more information.<br />
<br />
Begin with OpenRC 0.28 SysVinit is replaced with openrc-init, shutdown is replaced with openrc-shutdown, by using consolekit the system may hang up when shuting down from desktop session. So use {{AUR|elogind-openrc}} instead. Enable it with:<br />
<br />
# rc-update add elogind default<br />
<br />
Also you need to replace polkit-consolekit with {{AUR|polkit-elogind}}, or the system will alarm "not authorized to perform operation" when mounting usb device, and can't reboot or shutdown from the desktop session.<br />
<br />
== See also ==<br />
<br />
* [[Wikipedia:OpenRC]]<br />
* [https://wiki.gentoo.org/wiki/OpenRC Gentoo wiki]<br />
* [https://bbs.archlinux.org/viewtopic.php?id=152606 Forum thread about OpenRC in Arch]<br />
* [http://blog.notfoss.com/posts/openrc-on-arch-linux/ Blog: OpenRC on Arch Linux]<br />
* [https://wiki.manjaro.org/index.php?title=OpenRC,_an_alternative_to_systemd Manjaro wiki]</div>Stbinanhttps://wiki.archlinux.org/index.php?title=OpenRC&diff=485716OpenRC2017-08-18T02:55:50Z<p>Stbinan: /* Using OpenRC with a desktop environment */ Fix links</p>
<hr />
<div>[[Category:Init]]<br />
[[ja:OpenRC]]<br />
[[ru:OpenRC]]<br />
{{Related articles start}}<br />
{{Related|init}}<br />
{{Related articles end}}<br />
{{Warning|Arch Linux only has official support for [[systemd]]. When using OpenRC, please mention so in support requests.}}<br />
<br />
[https://wiki.gentoo.org/wiki/OpenRC OpenRC] is a service manager maintained by the Gentoo developers. OpenRC is dependency based and works with the system provided init program, normally [[SysVinit]].<br />
<br />
== Installation ==<br />
<br />
{{Accuracy|{{AUR|openrc-sysvinit}} removes {{Pkg|systemd-sysvcompat}}}}<br />
<br />
OpenRC and accompanying packages are available in the [[AUR]]. For details on init components, see [[Init]].<br />
<br />
Install either the {{AUR|openrc}} or {{AUR|openrc-git}} package. {{AUR|openrc-sysvinit}} or {{Pkg|busybox}} are used as the init process. Service files are available from the {{AUR|openrc-arch-services-git}} package.<br />
<br />
To maintain compability with {{AUR|initscripts-fork}}, configuration files are installed to {{ic|'''/etc/openrc/'''}}. The sysvinit init binary is installed to {{ic|/usr/bin/init-openrc}} for compability with {{Pkg|systemd-sysvcompat}} or similar packages.<br />
<br />
=== Booting ===<br />
<br />
For booting with OpenRC add {{Ic|1=init=/usr/bin/init-openrc}} to the [[kernel parameters]]. To switch back to systemd, remove the parameter again.<br />
<br />
The {{Ic|1=/etc/openrc/conf.d}} directory, and the {{Ic|1=/etc/openrc/rc.d}} file is used for configuration.<br />
<br />
== Configuration ==<br />
<br />
For general information on configuring OpenRC, see:<br />
<br />
* [http://www.calculate-linux.org/main/en/openrc_manuals OpenRC manuals]<br />
* [http://www.gentoo.org/doc/en/openrc-migration.xml OpenRC migration]<br />
* [http://wiki.gentoo.org/wiki/OpenRC gentoo wiki]. <br />
<br />
For instructions when migrating from [[systemd]], see [[Init#Configuration]].<br />
<br />
=== Services ===<br />
<br />
OpenRC services are enabled by issuing {{ic|rc-update add ''service_name'' ''runlevel''}} as root. It is recommended to at least enable the following services:<br />
{| class="wikitable"<br />
! Service name<br />
! [https://wiki.gentoo.org/wiki/OpenRC#Named_runlevels Runlevel]<br />
! Description<br />
|-<br />
| udev<br />
| sysinit<br />
| Device hot-plugging<br />
|-<br />
| alsa<br />
| default<br />
| [[ALSA]] state<br />
|-<br />
| acpid<br />
| default<br />
| ACPI events<br />
|-<br />
| dbus<br />
| default<br />
| Messaging bus<br />
|-<br />
| dcron<br />
| default<br />
| Scheduling<br />
|-<br />
| syslog-ng<br />
| default<br />
| System logs<br />
|}<br />
<br />
See also [https://wiki.gentoo.org/wiki/Systemd#Native_services Native services] and [[Daemons]].<br />
<br />
=== Network ===<br />
<br />
The network is configured through {{ic|newnet}}. [https://github.com/funtoo/openrc/blob/master/README.newnet] Modify the {{ic|/etc/openrc/conf.d/network}} file; both the {{ic|ip}} ({{Pkg|iproute2}}) and the {{ic|ifconfig}} ({{Pkg|net-tools}}) commands are supported. Below is an example configuration using {{ic|ip}}.<br />
<br />
{{bc|<br />
<nowiki>ip_eth0="192.168.1.2/24"<br />
defaultiproute="via 192.168.1.1"<br />
ifup_eth0="ip link set \$int mtu 1500"<br />
</nowiki>}}<br />
<br />
The network service is added to the boot runlevel by default, so no further action is required. See [[Network configuration]] for general networking information.<br />
<br />
{{Note|1=You may also use [[NetworkManager]], [[dhcpcd]] or {{AUR|netcfg}} by enabling the respective services. ''netcfg'' mimics the [[netctl]] behaviour (see [https://bbs.archlinux.org/viewtopic.php?pid=1489283#p1489283] if you want to enable profiles connection on booting - requires {{ic|wpa_actiond}}). See [https://www.archlinux.org/netcfg/features.html netcfg features].}}<br />
<br />
=== Boot logs ===<br />
<br />
To enable boot logging, uncomment the {{ic|1=rc_logger="YES"}} line in {{ic|/etc/openrc/rc.conf}}. When enabled, boot logs are stored in {{ic|/var/log/rc.log}}.<br />
<br />
=== Hostname ===<br />
<br />
OpenRC sets the hostname from {{ic|/etc/openrc/conf.d/hostname}}. The file looks as follows:<br />
<br />
{{bc|# Set to the hostname of this machine<br />
hostname<nowiki>=</nowiki>"myhostname"}}<br />
<br />
=== Kernel modules ===<br />
<br />
OpenRC uses {{ic|/etc/openrc/conf.d/modules}} instead of {{ic|/etc/modules-load.d}}. For example:<br />
<br />
{{hc|/etc/openrc/conf.d/modules|2=<br />
# You should consult your kernel documentation and configuration<br />
# for a list of modules and their options.<br />
<br />
modules="vboxdrv acpi_cpufreq"<br />
}}<br />
<br />
=== Locale ===<br />
<br />
Keyboard layout can be configured via {{ic|/etc/openrc/conf.d/keymaps}} and {{ic|/etc/openrc/conf.d/consolefont}}. You can also configure the settings through the {{ic|/etc/locale.conf}} file, which is sourced via {{ic|/etc/profile.d/locale.sh}}. <br />
<br />
See [http://wiki.gentoo.org/wiki/Localization/HOWTO#Keyboard_layout_for_the_console] and [[Locale]] for details.<br />
<br />
== Usage ==<br />
<br />
This section draws a parallel between [[systemd]] and other [[init]] systems.<br />
<br />
You can omit the {{ic|.service}} and {{ic|.target}} extensions, especially if temporarily editing the [[kernel parameters]].<br />
<br />
{| class="wikitable" width="100%"<br />
! systemd !! SysVinit !! OpenRC !! Description<br />
|-<br />
| {{ic|systemctl list-units}} || {{ic|rc.d list}} || {{ic|rc-status}} || List running services status<br />
|-<br />
| {{ic|systemctl --failed}} || || {{ic|rc-status --crashed}} || Check failed services<br />
|-<br />
| {{ic|systemctl --all}} || || {{ic|rc-update -v show}} || Display all available services.<br />
|-<br />
| {{ic|systemctl (start, stop, restart, status) daemon.service}} || {{ic|rc.d (start, stop, restart) daemon}} || {{ic|rc-service (start, stop, restart, status) daemon}} || Change service state.<br />
|- <br />
| {{ic|systemctl (enable, disable) daemon.service}} || {{ic|chkconfig daemon (on, off)}} || {{ic|rc-update (add, del) daemon}} || Turn service on or off.<br />
|-<br />
| {{ic|systemctl daemon-reload}} || {{ic|chkconfig daemon --add}} || || Create or modify configuration.<br />
|}<br />
<br />
== Tips and tricks ==<br />
<br />
=== Quiet booting ===<br />
<br />
To hide boot messages from OpenRC, you can edit {{ic|/etc/inittab}} and add {{ic|--quiet}} to every openrc command. For further information check with {{ic|$ openrc -h}}.<br />
<br />
== Troubleshooting ==<br />
<br />
=== Error while unmounting /tmp ===<br />
<br />
When shutting the system down, you might get an error message such as <br />
<br />
{{bc|* Unmounting /tmp ... <br />
* in use but fuser finds nothing [ !! ]}}<br />
<br />
This can be fixed by adding<br />
<br />
no_umounts="/tmp"<br />
<br />
to {{ic|/etc/openrc/conf.d/localmount}}<br />
<br />
{{Note|This problem occurs only if your tmp is mounted as a tmpfs.}}<br />
<br />
=== Disabling IPv6 does not work ===<br />
<br />
One option is to add:<br />
<br />
# Disable ipv6<br />
net.ipv6.conf.all.disable_ipv6 = 1<br />
<br />
in a file with a {{ic|.conf}} extension under {{ic|/etc/openrc/sysctl.d}}<br />
<br />
=== During shutdown remounting root as read-only fails ===<br />
<br />
If the above happens, edit the {{ic|/etc/openrc/init.d/mount-ro}} file and put:<br />
<br />
telinit u<br />
<br />
after the following line:<br />
<br />
# Flush all pending disk writes now<br />
sync; sync<br />
<br />
=== /etc/sysctl.conf not found ===<br />
<br />
By default, {{ic|sysctl --system}} is called to load the sysctl configuration. [https://github.com/OpenRC/openrc/blob/master/init.d/sysctl.Linux.in#L17] This includes the {{ic|/etc/sysctl.conf}} file, which was removed from Arch. [https://www.archlinux.org/news/deprecation-of-etcsysctlconf/]<br />
<br />
To prevent a missing file error, create the file:<br />
<br />
# touch /etc/sysctl.conf<br />
<br />
=== opentmpfiles-setup failed to start ===<br />
<br />
On booting openrc you may see lines like these :<br />
<br />
* Setting up tmpfiles.d entries ...<br />
chattr: Operation not supported while setting flags on /var/log/journal<br />
chattr: No such file or directory while trying to stat /var/log/journal/%m<br />
chattr: Operation not supported while setting flags on /var/log/journal/remote<br />
[ !! ]<br />
ERROR: opentmpfiles-setup failed to start<br />
<br />
This is caused by {{ic|/usr/lib/tmpfiles.d/journal-nocow.conf}} using options that are only valid if journal is on a btrfs filesystem.<br />
<br />
See https://github.com/OpenRC/opentmpfiles/issues/2 for details<br />
<br />
A workaround is to create an empty /etc/tmpfiles.d/journal-nocow.conf to override the settings.<br />
<br />
== Using OpenRC with a desktop environment ==<br />
<br />
If using ''OpenRC'' with a [[desktop environment]], ConsoleKit may help. Install the [https://gist.github.com/ad73f9087f39d7cadd8e service] to {{ic|/etc/openrc/init.d}}, and enable it:<br />
<br />
# rc-update add consolekit default<br />
<br />
See [[ConsoleKit]] for more information.<br />
<br />
Begin with OpenRC 0.28 SysVinit is replaced with openrc-init, shutdown is replaced with openrc-shutdown, by using consolekit the system may not shutdown correctly. So use [https://aur.archlinux.org/packages/elogind-openrc/ elogind-openrc] instead. Enable it with:<br />
<br />
# rc-update add elogind default<br />
<br />
Also you need to replace polkit-consolekit with [https://aur.archlinux.org/packages/polkit-elogind/ polkit-elogind], or the system will alarm "not authorized to perform operation" when mounting usb device, and can't reboot or shutdown from the desktop session.<br />
<br />
== See also ==<br />
<br />
* [[Wikipedia:OpenRC]]<br />
* [https://wiki.gentoo.org/wiki/OpenRC Gentoo wiki]<br />
* [https://bbs.archlinux.org/viewtopic.php?id=152606 Forum thread about OpenRC in Arch]<br />
* [http://blog.notfoss.com/posts/openrc-on-arch-linux/ Blog: OpenRC on Arch Linux]<br />
* [https://wiki.manjaro.org/index.php?title=OpenRC,_an_alternative_to_systemd Manjaro wiki]</div>Stbinanhttps://wiki.archlinux.org/index.php?title=OpenRC&diff=485715OpenRC2017-08-18T02:52:44Z<p>Stbinan: /* Using OpenRC with a desktop environment */ add desktop troubleshooting for openrc 0.28</p>
<hr />
<div>[[Category:Init]]<br />
[[ja:OpenRC]]<br />
[[ru:OpenRC]]<br />
{{Related articles start}}<br />
{{Related|init}}<br />
{{Related articles end}}<br />
{{Warning|Arch Linux only has official support for [[systemd]]. When using OpenRC, please mention so in support requests.}}<br />
<br />
[https://wiki.gentoo.org/wiki/OpenRC OpenRC] is a service manager maintained by the Gentoo developers. OpenRC is dependency based and works with the system provided init program, normally [[SysVinit]].<br />
<br />
== Installation ==<br />
<br />
{{Accuracy|{{AUR|openrc-sysvinit}} removes {{Pkg|systemd-sysvcompat}}}}<br />
<br />
OpenRC and accompanying packages are available in the [[AUR]]. For details on init components, see [[Init]].<br />
<br />
Install either the {{AUR|openrc}} or {{AUR|openrc-git}} package. {{AUR|openrc-sysvinit}} or {{Pkg|busybox}} are used as the init process. Service files are available from the {{AUR|openrc-arch-services-git}} package.<br />
<br />
To maintain compability with {{AUR|initscripts-fork}}, configuration files are installed to {{ic|'''/etc/openrc/'''}}. The sysvinit init binary is installed to {{ic|/usr/bin/init-openrc}} for compability with {{Pkg|systemd-sysvcompat}} or similar packages.<br />
<br />
=== Booting ===<br />
<br />
For booting with OpenRC add {{Ic|1=init=/usr/bin/init-openrc}} to the [[kernel parameters]]. To switch back to systemd, remove the parameter again.<br />
<br />
The {{Ic|1=/etc/openrc/conf.d}} directory, and the {{Ic|1=/etc/openrc/rc.d}} file is used for configuration.<br />
<br />
== Configuration ==<br />
<br />
For general information on configuring OpenRC, see:<br />
<br />
* [http://www.calculate-linux.org/main/en/openrc_manuals OpenRC manuals]<br />
* [http://www.gentoo.org/doc/en/openrc-migration.xml OpenRC migration]<br />
* [http://wiki.gentoo.org/wiki/OpenRC gentoo wiki]. <br />
<br />
For instructions when migrating from [[systemd]], see [[Init#Configuration]].<br />
<br />
=== Services ===<br />
<br />
OpenRC services are enabled by issuing {{ic|rc-update add ''service_name'' ''runlevel''}} as root. It is recommended to at least enable the following services:<br />
{| class="wikitable"<br />
! Service name<br />
! [https://wiki.gentoo.org/wiki/OpenRC#Named_runlevels Runlevel]<br />
! Description<br />
|-<br />
| udev<br />
| sysinit<br />
| Device hot-plugging<br />
|-<br />
| alsa<br />
| default<br />
| [[ALSA]] state<br />
|-<br />
| acpid<br />
| default<br />
| ACPI events<br />
|-<br />
| dbus<br />
| default<br />
| Messaging bus<br />
|-<br />
| dcron<br />
| default<br />
| Scheduling<br />
|-<br />
| syslog-ng<br />
| default<br />
| System logs<br />
|}<br />
<br />
See also [https://wiki.gentoo.org/wiki/Systemd#Native_services Native services] and [[Daemons]].<br />
<br />
=== Network ===<br />
<br />
The network is configured through {{ic|newnet}}. [https://github.com/funtoo/openrc/blob/master/README.newnet] Modify the {{ic|/etc/openrc/conf.d/network}} file; both the {{ic|ip}} ({{Pkg|iproute2}}) and the {{ic|ifconfig}} ({{Pkg|net-tools}}) commands are supported. Below is an example configuration using {{ic|ip}}.<br />
<br />
{{bc|<br />
<nowiki>ip_eth0="192.168.1.2/24"<br />
defaultiproute="via 192.168.1.1"<br />
ifup_eth0="ip link set \$int mtu 1500"<br />
</nowiki>}}<br />
<br />
The network service is added to the boot runlevel by default, so no further action is required. See [[Network configuration]] for general networking information.<br />
<br />
{{Note|1=You may also use [[NetworkManager]], [[dhcpcd]] or {{AUR|netcfg}} by enabling the respective services. ''netcfg'' mimics the [[netctl]] behaviour (see [https://bbs.archlinux.org/viewtopic.php?pid=1489283#p1489283] if you want to enable profiles connection on booting - requires {{ic|wpa_actiond}}). See [https://www.archlinux.org/netcfg/features.html netcfg features].}}<br />
<br />
=== Boot logs ===<br />
<br />
To enable boot logging, uncomment the {{ic|1=rc_logger="YES"}} line in {{ic|/etc/openrc/rc.conf}}. When enabled, boot logs are stored in {{ic|/var/log/rc.log}}.<br />
<br />
=== Hostname ===<br />
<br />
OpenRC sets the hostname from {{ic|/etc/openrc/conf.d/hostname}}. The file looks as follows:<br />
<br />
{{bc|# Set to the hostname of this machine<br />
hostname<nowiki>=</nowiki>"myhostname"}}<br />
<br />
=== Kernel modules ===<br />
<br />
OpenRC uses {{ic|/etc/openrc/conf.d/modules}} instead of {{ic|/etc/modules-load.d}}. For example:<br />
<br />
{{hc|/etc/openrc/conf.d/modules|2=<br />
# You should consult your kernel documentation and configuration<br />
# for a list of modules and their options.<br />
<br />
modules="vboxdrv acpi_cpufreq"<br />
}}<br />
<br />
=== Locale ===<br />
<br />
Keyboard layout can be configured via {{ic|/etc/openrc/conf.d/keymaps}} and {{ic|/etc/openrc/conf.d/consolefont}}. You can also configure the settings through the {{ic|/etc/locale.conf}} file, which is sourced via {{ic|/etc/profile.d/locale.sh}}. <br />
<br />
See [http://wiki.gentoo.org/wiki/Localization/HOWTO#Keyboard_layout_for_the_console] and [[Locale]] for details.<br />
<br />
== Usage ==<br />
<br />
This section draws a parallel between [[systemd]] and other [[init]] systems.<br />
<br />
You can omit the {{ic|.service}} and {{ic|.target}} extensions, especially if temporarily editing the [[kernel parameters]].<br />
<br />
{| class="wikitable" width="100%"<br />
! systemd !! SysVinit !! OpenRC !! Description<br />
|-<br />
| {{ic|systemctl list-units}} || {{ic|rc.d list}} || {{ic|rc-status}} || List running services status<br />
|-<br />
| {{ic|systemctl --failed}} || || {{ic|rc-status --crashed}} || Check failed services<br />
|-<br />
| {{ic|systemctl --all}} || || {{ic|rc-update -v show}} || Display all available services.<br />
|-<br />
| {{ic|systemctl (start, stop, restart, status) daemon.service}} || {{ic|rc.d (start, stop, restart) daemon}} || {{ic|rc-service (start, stop, restart, status) daemon}} || Change service state.<br />
|- <br />
| {{ic|systemctl (enable, disable) daemon.service}} || {{ic|chkconfig daemon (on, off)}} || {{ic|rc-update (add, del) daemon}} || Turn service on or off.<br />
|-<br />
| {{ic|systemctl daemon-reload}} || {{ic|chkconfig daemon --add}} || || Create or modify configuration.<br />
|}<br />
<br />
== Tips and tricks ==<br />
<br />
=== Quiet booting ===<br />
<br />
To hide boot messages from OpenRC, you can edit {{ic|/etc/inittab}} and add {{ic|--quiet}} to every openrc command. For further information check with {{ic|$ openrc -h}}.<br />
<br />
== Troubleshooting ==<br />
<br />
=== Error while unmounting /tmp ===<br />
<br />
When shutting the system down, you might get an error message such as <br />
<br />
{{bc|* Unmounting /tmp ... <br />
* in use but fuser finds nothing [ !! ]}}<br />
<br />
This can be fixed by adding<br />
<br />
no_umounts="/tmp"<br />
<br />
to {{ic|/etc/openrc/conf.d/localmount}}<br />
<br />
{{Note|This problem occurs only if your tmp is mounted as a tmpfs.}}<br />
<br />
=== Disabling IPv6 does not work ===<br />
<br />
One option is to add:<br />
<br />
# Disable ipv6<br />
net.ipv6.conf.all.disable_ipv6 = 1<br />
<br />
in a file with a {{ic|.conf}} extension under {{ic|/etc/openrc/sysctl.d}}<br />
<br />
=== During shutdown remounting root as read-only fails ===<br />
<br />
If the above happens, edit the {{ic|/etc/openrc/init.d/mount-ro}} file and put:<br />
<br />
telinit u<br />
<br />
after the following line:<br />
<br />
# Flush all pending disk writes now<br />
sync; sync<br />
<br />
=== /etc/sysctl.conf not found ===<br />
<br />
By default, {{ic|sysctl --system}} is called to load the sysctl configuration. [https://github.com/OpenRC/openrc/blob/master/init.d/sysctl.Linux.in#L17] This includes the {{ic|/etc/sysctl.conf}} file, which was removed from Arch. [https://www.archlinux.org/news/deprecation-of-etcsysctlconf/]<br />
<br />
To prevent a missing file error, create the file:<br />
<br />
# touch /etc/sysctl.conf<br />
<br />
=== opentmpfiles-setup failed to start ===<br />
<br />
On booting openrc you may see lines like these :<br />
<br />
* Setting up tmpfiles.d entries ...<br />
chattr: Operation not supported while setting flags on /var/log/journal<br />
chattr: No such file or directory while trying to stat /var/log/journal/%m<br />
chattr: Operation not supported while setting flags on /var/log/journal/remote<br />
[ !! ]<br />
ERROR: opentmpfiles-setup failed to start<br />
<br />
This is caused by {{ic|/usr/lib/tmpfiles.d/journal-nocow.conf}} using options that are only valid if journal is on a btrfs filesystem.<br />
<br />
See https://github.com/OpenRC/opentmpfiles/issues/2 for details<br />
<br />
A workaround is to create an empty /etc/tmpfiles.d/journal-nocow.conf to override the settings.<br />
<br />
== Using OpenRC with a desktop environment ==<br />
<br />
If using ''OpenRC'' with a [[desktop environment]], ConsoleKit may help. Install the [https://gist.github.com/ad73f9087f39d7cadd8e service] to {{ic|/etc/openrc/init.d}}, and enable it:<br />
<br />
# rc-update add consolekit default<br />
<br />
See [[ConsoleKit]] for more information.<br />
<br />
Begin with OpenRC 0.28 SysVinit is replaced with openrc-init, shutdown is replaced with openrc-shutdown, by using consolekit the system may not shutdown correctly. So use [elogind-openrc](https://aur.archlinux.org/packages/elogind-openrc/) instead. Enable it with:<br />
<br />
# rc-update add elogind default<br />
<br />
Also you need to replace polkit-consolekit with [polkit-elogind](https://aur.archlinux.org/packages/polkit-elogind/), or the system will alarm "not authorized to perform operation" when mounting usb device, and can't reboot or shutdown from the desktop session.<br />
<br />
== See also ==<br />
<br />
* [[Wikipedia:OpenRC]]<br />
* [https://wiki.gentoo.org/wiki/OpenRC Gentoo wiki]<br />
* [https://bbs.archlinux.org/viewtopic.php?id=152606 Forum thread about OpenRC in Arch]<br />
* [http://blog.notfoss.com/posts/openrc-on-arch-linux/ Blog: OpenRC on Arch Linux]<br />
* [https://wiki.manjaro.org/index.php?title=OpenRC,_an_alternative_to_systemd Manjaro wiki]</div>Stbinanhttps://wiki.archlinux.org/index.php?title=PCI_passthrough_via_OVMF&diff=473227PCI passthrough via OVMF2017-04-07T11:41:21Z<p>Stbinan: /* Troubleshooting */ Merge other relative items</p>
<hr />
<div>[[Category:Virtualization]]<br />
[[ja:OVMF による PCI パススルー]]<br />
The Open Virtual Machine Firmware ([http://www.tianocore.org/ovmf/ OVMF]) is a project to enable UEFI support for virtual machines. Starting with Linux 3.9 and recent versions of QEMU, it is now possible to passthrough a graphics card, offering the VM native graphics performance which is useful for graphic-intensive tasks.<br />
<br />
Provided you have a desktop computer with a spare GPU you can dedicate to the host (be it an integrated GPU or an old OEM card, the brands do not even need to match) and that your hardware supports it (see [[#Prerequisites]]), it is possible to have a VM of any OS with its own dedicated GPU and near-native performance. For more information on techniques see the background [http://www.linux-kvm.org/images/b/b3/01x09b-VFIOandYou-small.pdf presentation (pdf)]. <br />
<br />
== Prerequisites ==<br />
A VGA Passthrough relies on a number of technologies that are not ubiquitous as of today and might not be available on your hardware. You will not be able to do this on your machine unless the following requirements are met :<br />
<br />
* Your CPU must support hardware virtualization (for kvm) and IOMMU (for the passthrough itself)<br />
** [http://ark.intel.com/search/advanced?s=t&VTX=true&VTD=true List of compatible Intel CPUs (Intel VT-x and Intel VT-d)]<br />
** [http://support.amd.com/en-us/kb-articles/Pages/GPU120AMDRVICPUsHyperVWin8.aspx List of compatible AMD CPUs (AMD-V and AMD-Vi)]<br />
* Your motherboard must also support IOMMU<br />
** Both the chipset and the BIOS must support it. It is not always easy to tell at a glance whether or not this is the case, but there is a [http://wiki.xen.org/wiki/VTdHowTo fairly comprehensive list on the matter on the Xen wiki] as well as [[wikipedia:List_of_IOMMU-supporting_hardware|another one on Wikipedia]].<br />
* Your guest GPU ROM must support UEFI<br />
** If you can find [https://www.techpowerup.com/vgabios/ any ROM in this list] that applies to your specific GPU and is said to support UEFI, you are generally in the clear. All GPUs from 2012 and later should support this, as Microsoft made UEFI a requirement for devices to be marketed as compatible with Windows 8.<br />
<br />
You will probably want to have a spare monitor (the GPU will not display anything if there is no screen plugged in and using a VNC or Spice connection will not help your performance), as well as a mouse and a keyboard you can pass to your VM. If anything goes wrong, you will at least have a way to control your host machine this way.<br />
<br />
==Setting up IOMMU==<br />
IOMMU is a system specific IO mapping mechanism and can be used with most devices. IOMMU is a generic name for Intel VT-x/Intel and AMD AMD-V/AMD-Vi.<br />
===Enabling IOMMU===<br />
Ensure that AMD-VI/VT-d is enabled in your BIOS settings. Both normally show up alongside other CPU features (meaning they could be in an overclocking-related menu) either with their actual names ("Vt-d" or "AMD-VI"), legacy names ("Vanderpool" for Vt-x, "Pacifica" for AMD-V) or in more ambiguous terms such as "Virtualization technology", which may or may not be explained in the manual.<br />
<br />
You will also have to enable iommu support in the kernel itself through a [[Kernel_parameters|bootloader kernel option]]. Depending on your type of CPU, use either {{ic|intel_iommu<nowiki>=</nowiki>on}} for Intel CPUs (VT-d) or {{ic|amd_iommu<nowiki>=</nowiki>on}} for AMD CPUs (AMD-Vi).<br />
<br />
After rebooting, check dmesg to confirm that IOMMU has been correctly enabled:<br />
{{hc|dmesg<nowiki>|</nowiki>grep -e DMAR -e IOMMU|<br />
[ 0.000000] ACPI: DMAR 0x00000000BDCB1CB0 0000B8 (v01 INTEL BDW 00000001 INTL 00000001)<br />
[ 0.000000] Intel-IOMMU: enabled<br />
[ 0.028879] dmar: IOMMU 0: reg_base_addr fed90000 ver 1:0 cap c0000020660462 ecap f0101a<br />
[ 0.028883] dmar: IOMMU 1: reg_base_addr fed91000 ver 1:0 cap d2008c20660462 ecap f010da<br />
[ 0.028950] IOAPIC id 8 under DRHD base 0xfed91000 IOMMU 1<br />
[ 0.536212] DMAR: No ATSR found<br />
[ 0.536229] IOMMU 0 0xfed90000: using Queued invalidation<br />
[ 0.536230] IOMMU 1 0xfed91000: using Queued invalidation<br />
[ 0.536231] IOMMU: Setting RMRR:<br />
[ 0.536241] IOMMU: Setting identity map for device 0000:00:02.0 [0xbf000000 - 0xcf1fffff]<br />
[ 0.537490] IOMMU: Setting identity map for device 0000:00:14.0 [0xbdea8000 - 0xbdeb6fff]<br />
[ 0.537512] IOMMU: Setting identity map for device 0000:00:1a.0 [0xbdea8000 - 0xbdeb6fff]<br />
[ 0.537530] IOMMU: Setting identity map for device 0000:00:1d.0 [0xbdea8000 - 0xbdeb6fff]<br />
[ 0.537543] IOMMU: Prepare 0-16MiB unity mapping for LPC<br />
[ 0.537549] IOMMU: Setting identity map for device 0000:00:1f.0 [0x0 - 0xffffff]<br />
[ 2.182790] [drm] DMAR active, disabling use of stolen memory}}<br />
<br />
===Ensuring that the groups are valid===<br />
<br />
The following script should allow you to see how your various PCI devices are mapped to IOMMU groups. If it does not return anything, you either have not enabled IOMMU support properly or your hardware does not support it.<br />
<br />
#!/bin/bash<br />
shopt -s nullglob<br />
for d in /sys/kernel/iommu_groups/*/devices/*; do <br />
n=${d#*/iommu_groups/*}; n=${n%%/*}<br />
printf 'IOMMU Group %s ' "$n"<br />
lspci -nns "${d##*/}"<br />
done;<br />
<br />
Example output:<br />
<br />
IOMMU Group 0 00:00.0 Host bridge [0600]: Intel Corporation 2nd Generation Core Processor Family DRAM Controller [8086:0104] (rev 09)<br />
IOMMU Group 1 00:16.0 Communication controller [0780]: Intel Corporation 6 Series/C200 Series Chipset Family MEI Controller #1 [8086:1c3a] (rev 04)<br />
IOMMU Group 2 00:19.0 Ethernet controller [0200]: Intel Corporation 82579LM Gigabit Network Connection [8086:1502] (rev 04)<br />
IOMMU Group 3 00:1a.0 USB controller [0c03]: Intel Corporation 6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 [8086:1c2d] (rev <br />
...<br />
An IOMMU group is the smallest set of physical devices that can be passed to a virtual machine. For instance, in the example above, both the GPU in 06:00.0 and its audio controller in 6:00.1 belong to IOMMU group 13 and can only be passed together. The frontal USB controller, however, has its own group (group 2) which is separate from both the USB expansion controller (group 10) and the rear USB controller (group 4), meaning that [[#USB_controller|any of them could be passed to a VM without affecting the others]].<br />
<br />
===Gotchas===<br />
====Plugging your guest GPU in an unisolated CPU-based PCIe slot====<br />
Not all PCI-E slots are the same. Most motherboards have PCIe slots provided by both the CPU and the PCH. Depending on your CPU, it is possible that your processor-based PCIe slot does not support isolation properly, in which case the PCI slot itself will be appear to be grouped with the device that is connected to it.<br />
<br />
IOMMU Group 1 00:01.0 PCI bridge: Intel Corporation Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port (rev 09)<br />
IOMMU Group 1 01:00.0 VGA compatible controller: NVIDIA Corporation GM107 [GeForce GTX 750] (rev a2)<br />
IOMMU Group 1 01:00.1 Audio device: NVIDIA Corporation Device 0fbc (rev a1)<br />
<br />
This is fine so long as only your guest GPU is included in here, such as above. Depending on what is plugged in your other PCIe slots and whether they are allocated to your CPU or your PCH, you may find yourself with additional devices within the same group, which would force you to pass those as well. If you are ok with passing everything that is in there to your VM, you are free to continue. Otherwise, you will either need to try and plug your GPU in your other PCIe slots (if you have any) and see if those provide isolation from the rest or to install the ACS override patch, which comes with its own drawbacks. See [[#Bypassing the IOMMU groups (ACS override patch)]] for more information.<br />
<br />
{{note|If they are grouped with other devices in this manner, pci root ports and bridges should neither be bound to vfio at boot, nor be added to the VM.}}<br />
<br />
==Isolating the GPU==<br />
Due to their size and complexity, GPU drivers do not tend to support dynamic rebinding very well, so you cannot just have some GPU you use on the host be transparently passed to a VM without consequences. It is generally preferable to bind them with a placeholder driver instead. This will stop other drivers from attempting to claim it, and will force the GPU to remain inactive while a VM is not running. There are two methods for doing this, but it is recommended to use vfio-pci if your kernel supports it.<br />
<br />
{{warning|Once you reboot after this procedure, whatever GPU you have configured will no longer be usable on the host until you reverse the manipulation. Make sure the GPU you intend to use on the host is properly configured before doing this.}}<br />
<br />
===Using vfio-pci===<br />
Starting with Linux 4.1, the kernel includes vfio-pci, which is functionally similar to pci-stub with a few added bonuses, such as switching devices into their D3 state when they are not in use. If your system supports it, which you can try by running the following command, you should use it. If it returns en error, you will have to rely on pci-stub instead.<br />
<br />
{{hc|$ modinfo vfio-pci|<br />
filename: /lib/modules/4.4.5-1-ARCH/kernel/drivers/vfio/pci/vfio-pci.ko.gz<br />
description: VFIO PCI - User Level meta-driver<br />
author: Alex Williamson <alex.williamson@redhat.com><br />
...}}<br />
<br />
Vfio-pci normally targets PCI devices by ID, meaning you only need to specify the IDs of the devices you intend to passthrough. For the following IOMMU group, you would want to bind vfio-pci with {{ic|10de:13c2}} and {{ic|10de:0fbb}}, which will be used as example values for the rest of this section.<br />
<br />
IOMMU Group 13 06:00.0 VGA compatible controller: NVIDIA Corporation GM204 [GeForce GTX 970] [10de:13c2] (rev a1)<br />
IOMMU Group 13 06:00.1 Audio device: NVIDIA Corporation GM204 High Definition Audio Controller [10de:0fbb] (rev a1)}}<br />
<br />
{{note|You cannot specify which device to isolate using vendor-device ID pairs if the host GPU and the guest GPU share the same pair (i.e : if both are the same model). If this is your case, read the [[#Using_identical_guest_and_host_GPUs|Special procedures]] section instead.}}<br />
<br />
You can then add those vendor-device ID pairs to the default parameters passed to vfio-pci whenever it is inserted into the kernel.<br />
{{hc|1=/etc/modprobe.d/vfio.conf|2=options vfio-pci ids=10de:13c2,10de:0fbb}}<br />
{{note|If, as noted [[#Plugging_your_guest_GPU_in_an_unisolated_CPU-based_PCIe_slot|here]], your pci root port is part of your IOMMU group, you '''must not''' pass its ID to {{ic|vfio-pci}}, as it needs to remain attached to the host to function properly. Any other device within that group, however, should be left for {{ic|vfio-pci}} to bind with.}}<br />
<br />
This, however, does not guarantee that vfio-pci will be loaded before other graphics drivers. To ensure that, we need to statically bind it in the kernel image alongside with its dependencies. That means adding, in this order, {{ic|vfio}}, {{ic|vfio_iommu_type1}}, {{ic|vfio_pci}} and {{ic|vfio_virqfd}} to [[mkinitcpio]]:<br />
<br />
{{hc|1=/etc/mkinitcpio.conf|2=MODULES="... vfio vfio_iommu_type1 vfio_pci vfio_virqfd ..."}}<br />
<br />
{{note|If you also have another driver loaded this way for [[Kernel_mode_setting#Early_KMS_start|early modesetting]] (such as "nouveau", "radeon", "amdgpu", "i915", etc.), all of the aforementioned VFIO modules must precede it.}}<br />
<br />
Also, ensure that the modconf hook is included in the HOOKS list of mkinitcpio.conf:<br />
<br />
{{hc|1=/etc/mkinitcpio.conf|2=HOOKS="... modconf ..."}}<br />
<br />
Since new modules have been added to the initramfs configuration, it must be regenerated. Should you change the IDs of the devices in {{ic|/etc/modprobe.d/vfio.conf}}, you will also have to regenerate it, as those parameters must be specified in the initramfs to be known during the early boot stages.<br />
{{bc|# mkinitcpio -p linux}}<br />
{{Note|If you are using a non-standard kernel, such as {{ic|linux-vfio}}, replace {{ic|linux}} with whichever kernel you intend to use.}}<br />
<br />
Reboot and verify that vfio-pci has loaded properly and that it is now bound to the right devices.<br />
{{hc|$ dmesg <nowiki>|</nowiki> grep -i vfio |<br />
[ 0.329224] VFIO - User Level meta-driver version: 0.3<br />
[ 0.341372] vfio_pci: add [10de:13c2[ffff:ffff]] class 0x000000/00000000<br />
[ 0.354704] vfio_pci: add [10de:0fbb[ffff:ffff]] class 0x000000/00000000<br />
[ 2.061326] vfio-pci 0000:06:00.0: enabling device (0100 -> 0103)}}<br />
<br />
It isn't necessary for all devices (or even expected device) from vfio.conf to be in dmesg output. Sometimes device doesn't appear in output at boot but actually is able to be visible and operatable in guest VM.<br />
<br />
{{hc|$ lspci -nnk -d 10de:13c2|<br />
06:00.0 VGA compatible controller: NVIDIA Corporation GM204 [GeForce GTX 970] [10de:13c2] (rev a1)<br />
Kernel driver in use: vfio-pci<br />
Kernel modules: nouveau nvidia}}<br />
<br />
{{hc|$ lspci -nnk -d 10de:0fbb|<br />
06:00.1 Audio device: NVIDIA Corporation GM204 High Definition Audio Controller [10de:0fbb] (rev a1)<br />
Kernel driver in use: vfio-pci<br />
Kernel modules: snd_hda_intel}}<br />
<br />
===Using pci-stub (legacy method, pre-4.1 kernels)===<br />
If your kernel does not support vfio-pci, you can use the pci-stub module instead.<br />
<br />
Pci-stub normally targets PCI devices by ID, meaning you only need to specify the IDs of the devices you intend to passthrough. For the following IOMMU group, you would want to bind vfio-pci with {{ic|10de:13c2}} and {{ic|10de:0fbb}}, which will be used as example values for the rest of this section.<br />
<br />
IOMMU group 13 06:00.0 VGA compatible controller: NVIDIA Corporation GM204 [GeForce GTX 970] [10de:13c2] (rev a1)<br />
IOMMU group 13 06:00.1 Audio device: NVIDIA Corporation GM204 High Definition Audio Controller [10de:0fbb] (rev a1)}}<br />
<br />
{{note|You cannot specify which device to isolate using vendor-device ID pairs if the host GPU and the guest GPU share the same pair (i.e : if both are the same model). If this is your case, read the [[#Using_identical_guest_and_host_GPUs|Special procedures]] section instead.}}<br />
Most linux distros (including Arch Linux) have pci-stub built statically within the kernel image. If for any reason it needs to be loaded as a module in your case, you will need to bind it yourself using whatever tool your distro provides for this, such as {{ic|mkinitpcio}} for Arch.<br />
{{hc|<nowiki>/etc/mkinitcpio.conf</nowiki>|<nowiki>MODULES="... pci-stub ..."</nowiki>}}<br />
<br />
If you did need to add this module to your kernel image configuration manually, you must also regenerate it.<br />
{{bc|# mkinitcpio -p linux}}<br />
{{Note|If you are using a non-standard kernel, such as {{ic|linux-vfio}}, replace {{ic|linux}} with whichever kernel you intend to use.}}<br />
<br />
Add the relevant PCI device IDs to the kernel command line:<br />
{{hc|<nowiki>/etc/default/grub</nowiki>|<nowiki>...<br />
GRUB_CMDLINE_LINUX_DEFAULT="... pci-stub.ids=10de:13c2,10de:0fbb ..."<br />
...</nowiki>}}<br />
{{note|If, as noted [[#Plugging_your_guest_GPU_in_an_unisolated_CPU-based_PCIe_slot|here]], your pci root port is part of your IOMMU group, you '''must not''' pass its ID to {{ic|pci-stub}}, as it needs to remain attached to the host to function properly. Any other device within that group, however, should be left for {{ic|pci-stub}} to bind with.}}<br />
<br />
Reload the grub configuration:<br />
{{bc|# grub-mkconfig -o /boot/grub/grub.cfg}}<br />
<br />
Check dmesg output for successful assignment of the device to pci-stub:<br />
{{hc|dmesg <nowiki>|</nowiki> grep pci-stub|<br />
[ 2.390128] pci-stub: add 10DE:13C2 sub<nowiki>=</nowiki>FFFFFFFF:FFFFFFFF cls<nowiki>=</nowiki>00000000/00000000<br />
[ 2.390143] pci-stub 0000:06:00.0: claimed by stub<br />
[ 2.390150] pci-stub: add 10DE:0FBB sub<nowiki>=</nowiki>FFFFFFFF:FFFFFFFF cls<nowiki>=</nowiki>00000000/00000000<br />
[ 2.390159] pci-stub 0000:06:00.1: claimed by stub}}<br />
<br />
==Setting up an OVMF-based guest VM==<br />
OVMF is an open-source UEFI firmware for QEMU virtual machines. While it's possible to use SeaBIOS to get similar results to an actual PCI passthough, the setup process is different and it is generally preferable to use the EFI method if your hardware supports it.<br />
<br />
===Configuring libvirt===<br />
[[Libvirt]] is a wrapper for a number of virtualization utilities that greatly simplifies the configuration and deployment process of virtual machines. In the case of KVM and QEMU, the frontend it provides allows us to avoid dealing with the permissions for QEMU and make it easier to add and remove various devices on a live VM. Its status as a wrapper, however, means that it might not always support all of the latest qemu features, which could end up requiring the use of a wrapper script to provide some extra arguments to QEMU.<br />
<br />
After installing {{Pkg|qemu}}, {{Pkg|libvirt}}, {{AUR|ovmf-git}} and {{Pkg|virt-manager}}, add the path to your OVMF firmware image and runtime variables template to your libvirt config so {{ic|virt-install}} or {{ic|virt-manager}} can find those later on.<br />
<br />
{{hc|/etc/libvirt/qemu.conf|<br />
<nowiki>nvram = [</nowiki><br />
"/usr/share/ovmf/x64/ovmf_x64.bin:/usr/share/ovmf/x64/ovmf_vars_x64.bin"<br />
]<br />
}}<br />
<br />
You can now [[enable]] and start {{ic|libvirtd}} and its logging component.<br />
<br />
{{bc|<br />
# systemctl enable --now libvirtd<br />
# systemctl enable virtlogd.socket}}<br />
<br />
===Setting up the guest OS===<br />
The process of setting up a VM using {{ic|virt-manager}} is mostly self explainatory, as most of the process comes with fairly comprehensive on-screen instructions. However, you should pay special attention to the following steps :<br />
* When the VM creation wizard asks you to name your VM, check the "Customize before install" checkbox.<br />
* In the "Overview" section, set your firmware to "UEFI". If the option is grayed out, make sure that you have correctly specified the location of your firmware in {{ic|/etc/libvirt/qemu.conf}} and restart {{ic|libvirtd.service}}.<br />
* In the "CPUs" section, change your CPU model to "host-passthrough". If it is not in the list, you will have to type it by hand. This will ensure that your CPU is detected properly, since it causes libvirt to expose your CPU capabilities exactly as they are instead of only those it recognizes (which is the preferred default behavior to make CPU behavior easier to reproduce). Without it, some applications may complain about your CPU being of an unknown model.<br />
* If you want to minimize IO overhead, go into "Add Hardware" and add a Controller for SCSI drives of the "VirtIO SCSI" model. You can then change the default IDE disk for a SCSI disk, which will bind to said controller.<br />
** Windows VMs will not recognize those drives by default, so you need to download the ISO containing the drivers from [https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/latest-virtio/ here] and add an IDE (or SATA for Windows 8.1 and newer) CD-ROM storage device linking to said ISO, otherwise you will not be able to get Windows to recognize it during the installation process. When prompted to select a disk to install windows on, load the drivers contained on the CD-ROM under ''vioscsi''.<br />
<br />
The rest of the installation process will take place as normal using a standard QXL video adapter running in a window. At this point, there is no need to install additional drivers for the rest of the virtual devices, since most of them will be removed later on. Once the guest OS is done installing, simply turn off the virtual machine.<br />
<br />
===Attaching the PCI devices===<br />
With the installation done, it's now possible to edit the hardware details in libvirt and remove virtual integration devices, such as the spice channel and virtual display, the QXL video adapter, the emulated mouse and keyboard and the USB tablet device. Since that leaves you with no input devices, you may want to bind a few USB host devices to your VM as well, but remember to '''leave at least one mouse and/or keyboard assigned to your host''' in case something goes wrong with the guest. At this point, it also becomes possible to attach the PCI device that was isolated earlier; simply click on "Add Hardware" and select the PCI Host Devices you want to passthrough. If everything went well, the screen plugged into your GPU should show the OVMF splash screen and your VM should start up normally. From there, you can setup the drivers for the rest of your VM.<br />
<br />
===Gotchas===<br />
====Using a non-EFI image on an OVMF-based VM====<br />
The OVMF firmware does not support booting off non-EFI mediums. If the installation process drops you in a UEFI shell right after booting, you may have an invalid EFI boot media. Try using an alternate linux/windows image to determine if you have an invalid media.<br />
<br />
==Performance tuning==<br />
Most use cases for PCI passthroughs relate to performance-intensive domains such as video games and GPU-accelerated tasks. While a PCI passthrough on its own is a step towards reaching native performance, there are still a few ajustments on the host and guest to get the most out of your VM.<br />
<br />
===CPU pinning===<br />
The default behavior for KVM guests is to run operations coming from the guest as a number of threads representing virtual processors. Those threads are managed by the Linux scheduler like any other thread and are dispatched to any available CPU cores based on niceness and priority queues. Since switching between threads adds a bit of overhead (because context switching forces the core to change its cache between operations), this can noticeably harm performance on the guest. CPU pinning aims to resolve this as it overrides process scheduling and ensures that the VM threads will always run and only run on those specific cores. Here, for instance, the guest cores 0, 1, 2 and 3 are mapped to the host cores 4, 5, 6 and 7 respectively.<br />
<br />
{{hc|<nowiki>EDITOR=nano virsh edit myPciPassthroughVm</nowiki>|...<br />
<nowiki><vcpu placement='static'>4</vcpu><br />
<cputune><br />
<vcpupin vcpu='0' cpuset='4'/><br />
<vcpupin vcpu='1' cpuset='5'/><br />
<vcpupin vcpu='2' cpuset='6'/><br />
<vcpupin vcpu='3' cpuset='7'/><br />
</cputune></nowiki><br />
...}}<br />
<br />
====The case of Hyper-threading====<br />
If your CPU supports hardware multitasking, also known as Hyper-threading on Intel chips, there are two ways you can go with your CPU pinning. That is, Hyper-threading is simply a very efficient way of running two threads on one CPU at any given time, so while it may give you 8 logical cores on what would otherwise be a quad-core CPU, if the physical core is overloaded, the logical core won't be of any use. One could pin their VM threads on 2 physical cores and their 2 respective threads, but any task overloading those two cores won't be helped by the extra two logical cores, since in the end you're only passing through two cores out of four, not four out of eight. What you should do knowing this depends on what you intend to do with your host while your VM is running.<br />
<br />
This is the abridged content of {{ic|/proc/cpuinfo}} on a quad-core machine with hyper-threading.<br />
{{hc|<nowiki>$ cat /proc/cpuinfo | grep -e "processor" -e "core id" -e "^$"</nowiki>|<br />
processor : 0<br />
core id : 0<br />
<br />
processor : 1<br />
core id : 1<br />
<br />
processor : 2<br />
core id : 2<br />
<br />
processor : 3<br />
core id : 3<br />
<br />
processor : 4<br />
core id : 0<br />
<br />
processor : 5<br />
core id : 1<br />
<br />
processor : 6<br />
core id : 2<br />
<br />
processor : 7<br />
core id : 3}}<br />
<br />
If you don't intend to be doing any computation-heavy work on the host (or even anything at all) at the same time as you would on the VM, it would probably be better to pin your VM threads across all of your logical cores, so that the VM can fully take advantage of the spare CPU time on all your cores.<br />
<br />
On the quad-core machine mentioned above, it would look like this :<br />
{{hc|<nowiki>EDITOR=nano virsh edit myPciPassthroughVm</nowiki>|...<br />
<nowiki><vcpu placement='static'>4</vcpu><br />
<cputune><br />
<vcpupin vcpu='0' cpuset='4'/><br />
<vcpupin vcpu='1' cpuset='5'/><br />
<vcpupin vcpu='2' cpuset='6'/><br />
<vcpupin vcpu='3' cpuset='7'/><br />
</cputune><br />
...<br />
<cpu mode='custom' match='exact'><br />
...<br />
<topology sockets='1' cores='4' threads='1'/><br />
...<br />
</cpu></nowiki><br />
...}}<br />
<br />
If you would instead prefer to have the host and guest running intensive tasks at the same time, it would then be preferable to pin a limited amount of physical cores and their respective threads on the guest and leave the rest to the host to avoid the two competing for CPU time.<br />
<br />
On the quad-core machine mentioned above, it would look like this :<br />
{{hc|<nowiki>EDITOR=nano virsh edit myPciPassthroughVm</nowiki>|...<br />
<nowiki><vcpu placement='static'>4</vcpu><br />
<cputune><br />
<vcpupin vcpu='0' cpuset='2'/><br />
<vcpupin vcpu='1' cpuset='3'/><br />
<vcpupin vcpu='2' cpuset='6'/><br />
<vcpupin vcpu='3' cpuset='7'/><br />
</cputune><br />
...<br />
<cpu mode='custom' match='exact'><br />
...<br />
<topology sockets='1' cores='2' threads='2'/><br />
...<br />
</cpu></nowiki><br />
...}}<br />
<br />
===Static huge pages===<br />
When dealing with applications that require large amounts of memory, memory latency can become a problem since the more memory pages are being used, the more likely it is that this application will attempt to access information accross multiple memory "pages", which is the base unit for memory allocation. Resolving the actual address of the memory page takes multiple steps, and so CPUs normally cache information on recently used memory pages to make subsequent uses on the same pages faster. Applications using large amounts of memory run into a problem where, for instance, a virtual machine uses 4GB of memory divided into 4kB pages (which is the default size for normal pages), meaning that such cache misses can become extremely frequent and greatly increase memory latency. Huge pages exist to mitigate this issue by giving larger individual pages to those applications, increasing the odds that multiple operations will target the same page in succession. This is normally handeled with transparent huge pages, which dynamically manages hugepages to keep up with the demand.<br />
<br />
On a VM with a PCI passthrough, however, it is '''not possible''' to benefit from transparent huge pages, as IOMMU requires that the guest's memory be allocated and pinned as soon as the VM starts. It is therefore required to allocate huge pages statically in order to benefit from them. <br />
<br />
{{warning|Do note that static huge pages lock down the allocated amount of memory, making it unavailable for applications that are not configured to use them. Allocating 4GBs worth of huge pages on a machine with 8GBs of memory will only leave you with 4GBs of available memory on the host '''even when the VM is not running'''.}}<br />
<br />
To allocate huge pages at boot, one must simply specify the desired amount on their kernel comand line with {{ic|<nowiki>hugepages=x</nowiki>}}. For instance, reserving 1024 pages with {{ic|<nowiki>hugepages=1024</nowiki>}} and the default size of 2048kB per huge page creates 2GBs worth of memory for the virtual machine to use.<br />
<br />
Also, since static huge pages can only be used by applications that specifically request it, you must add this section in your libvirt domain configuration to allow kvm to benefit from them :<br />
{{hc|<nowiki>EDITOR=nano virsh edit myPciPassthroughVm</nowiki>|...<br />
<memoryBacking><br />
<hugepages/><br />
</memoryBacking><br />
...}}<br />
<br />
=== CPU frequency governor ===<br />
<br />
Depending on the way your [[CPU_frequency_scaling|CPU governor]] is configured, the VM threads may not hit the CPU load thresholds for the frequency to ramp up. Indeed, KVM cannot actually change the CPU frequency on its own, which can be a problem if the it does not scale up with vCPU usage as it would result in underwhelming performance. An easy way to see if it behaves correctly is to check if the frequency reported by {{ic|watch lscpu}} goes up when running a CPU-intensive task on the guest. If you are indeed experiencing stutter and the frequency does not go up to reach its reported maximum, it may be due to [https://lime-technology.com/forum/index.php?topic=46664.msg447678#msg447678 cpu scaling being controlled by the host OS]. In this case, try setting all cores to maximum frequency to see if this improves performance. Note that if you're using a modern intel chip with the default pstate driver, cpupower commands will be [[CPU_frequency_scaling#CPU_frequency_driver|ineffective]], so monitor {{ic|/proc/cpuinfo}} to make sure your cpu is actually at max frequency.<br />
<br />
=== High DPC Latency ===<br />
{{Accuracy|As far as I can tell all virtio modules listed here are for virtual devices used when Linux runs as a guest. Loading them on the host serves no purpose.}}<br />
If you are experiencing high DPC and/or interrupt latency in your Guest VM, ensure you have [[Kernel_modules#Manual_module_handling|loaded the needed virtio kernel modules]] on the host kernel. Loadable virtio kernel modules include: {{ic|virtio-pci, virtio-net, virtio-blk, virtio-balloon, virtio-ring}} and {{ic|virtio}}. <br />
<br />
After loading one or more of these modules, {{ic|lsmod <nowiki>|</nowiki> grep virtio}} executed on the host should not return empty.<br />
<br />
== Special procedures ==<br />
<br />
Certain setups require specific configuration tweaks in order to work properly. If you're having problems getting your host or your VM to work properly, see if your system matches one of the cases below and try adjusting your configuration accordingly.<br />
<br />
=== Using identical guest and host GPUs ===<br />
{{Expansion|A number of users have been having issues with this, it should probably be adressed by the article.|Talk:PCI passthrough via OVMF#Additionnal_sections}}<br />
Due to how both pci-stub and vfio-pci use your vendor and device id pair to identify which device they need to bind to at boot, if you have two GPUs sharing such an ID pair you won't be able to get your passthough driver to bind with just one of them. This sort of setup makes it necessary to use a script, so that whichever driver you're using is instead assigned by pci bus address using the {{ic|driver_override}} mechanism.<br />
<br />
Here, we will make a script to bind vfio-pci to all GPUs but the boot gpu. Create the script "/sbin/vfio-pci-override.sh":<br />
<br />
#!/bin/sh<br />
<br />
for i in /sys/devices/pci*/*/boot_vga; do<br />
if [ $(cat "$i") -eq 0 ]; then<br />
GPU="${i%/boot_vga}"<br />
AUDIO="$(echo "$GPU" | sed -e "s/0$/1/")"<br />
echo "vfio-pci" > "$GPU/driver_override"<br />
if [ -d "$AUDIO" ]; then<br />
echo "vfio-pci" > "$AUDIO/driver_override"<br />
fi<br />
fi<br />
done<br />
<br />
modprobe -i vfio-pci<br />
<br />
Create /etc/modprobe.d/vfio.conf with the following:<br />
install vfio-pci /sbin/vfio-pci-override.sh<br />
<br />
Edit /etc/mkinitcpio.conf<br />
<br />
Remove any video drivers from MODULES, and add vfio-pci, and vfio_iommu_type1<br />
MODULES="ext4 vfat vfio-pci vfio_iommu_type1"<br />
<br />
Add "/etc/modprobe.d/vfio.conf" and "/sbin/vfio-pci-override.sh" to FILES:<br />
FILES="/etc/modprobe.d/vfio.conf /sbin/vfio-pci-override.sh"<br />
<br />
Regenerate your initramfs, and reboot:<br />
mkinitcpio -p linux<br />
<br />
=== Passing the boot GPU to the guest ===<br />
{{Expansion|Not possible at the time as far as I'm aware, but a common issue on various forums.|Talk:PCI passthrough via OVMF#Additionnal_sections}}<br />
The GPU marked as {{ic|boot_vga}} is a special case when it comes to doing PCI passthroughs, since the BIOS needs to use it in order to display things like boot messages or the BIOS configuration menu. To do that, it makes [https://www.redhat.com/archives/vfio-users/2016-May/msg00224.html a copy of the VGA boot ROM which can then be freely modified]. This modified copy is the version the system gets to see, which the passthrough driver may reject as invalid. As such, it is generally reccomanded to change the boot GPU in the BIOS configuration so the host GPU is used instead or, if that's not possible, to swap the host and guest cards in the machine itself.<br />
<br />
=== Bypassing the IOMMU groups (ACS override patch) ===<br />
<br />
If you find your PCI devices grouped among others that you do not wish to pass through, you may be able to seperate them using Alex Williamson's ACS override patch. Make sure you understand [http://vfio.blogspot.com/2014/08/iommu-groups-inside-and-out.html the potential risk] of doing so. <br />
<br />
You will need a kernel with the patch applied. The easiest method to acquiring this is through the {{AUR|linux-vfio}} package. <br />
<br />
In addition, the ACS override patch needs to be enabled with kernel command line options. The patch file adds the following documentation:<br />
<br />
pcie_acs_override =<br />
[PCIE] Override missing PCIe ACS support for:<br />
downstream<br />
All downstream ports - full ACS capabilties<br />
multifunction<br />
All multifunction devices - multifunction ACS subset<br />
id:nnnn:nnnn<br />
Specfic device - full ACS capabilities<br />
Specified as vid:did (vendor/device ID) in hex<br />
<br />
The option {{ic|pcie_acs_override<nowiki>=</nowiki>downstream}} is typically sufficient.<br />
<br />
After installation and configuration, reconfigure your [[Kernel parameters|bootloader kernel parameters]] to load the new kernel with the {{ic|pcie_acs_override<nowiki>=</nowiki>}} option enabled.<br />
<br />
== QEMU without libvirtd (can switch GPUs without reboot) ==<br />
<br />
{{Remove|Too specific to warrant an article section. Some of the links could be moved to the [[#See also]] section.}}<br />
<br />
[https://git.mel.vin/melvin/scripts/tree/master/qemu] starts Samba and Synergy, runs the VM and closes everything after the VM is shut down. This method does '''not''' require libvirtd to be running or configured.<br />
<br />
With these new scripts, is it possible to switch GPUs without rebooting, only a restart of the X session is needed. This is all handled by a tiny shell script that runs in the tty. When you log in the tty, it will ask which card you would like to use if you autolaunch the shell script.<br />
<br />
[https://www.redhat.com/archives/vfio-users/2016-May/msg00187.html vfio-users : Full set of (runtime) scripts for VFIO + Qemu CLI]<br />
<br />
[https://www.redhat.com/archives/vfio-users/2015-August/msg00020.html vfio-users : Example configuration with CLI Qemu (working VM => host audio)]<br />
<br />
==Passing though other devices==<br />
===USB controller===<br />
If your motherboard has multiple USB controllers mapped to multiple groups, it is possible to pass those instead of USB devices. Passing an actual controller over an individual USB device provides the following advantages : <br />
<br />
* If a device disconnects or changes ID over the course of an given operation (such as a phone undergoing an update), the VM will not suddenly stop seeing it.<br />
* Any USB port managed by this controller is directly handled by the VM and can have its devices unplugged, replugged and changed without having to notify the hypervisor.<br />
* Libvirt will not complain if one of the USB devices you usually pass to the guest is missing when starting the VM.<br />
<br />
Unlike with GPUs, drivers for most USB controllers do not require any specific configuration to work on a VM and control can normally be passed back and forth between the host and guest systems with no side effects.<br />
<br />
{{Warning|Make sure your USB controller supports resetting :[[#Passing through a device that does not support resetting]]}}<br />
<br />
You can find out which PCI devices correspond to which controller and how various ports and devices are assigned to each one of them using this command :<br />
<br />
{{hc|$ <nowiki>for usb_ctrl in $(find /sys/bus/usb/devices/usb* -maxdepth 0 -type l); do pci_path="$(dirname "$(realpath "${usb_ctrl}")")"; echo "Bus $(cat "${usb_ctrl}/busnum") --> $(basename $pci_path) (IOMMU group $(basename $(realpath $pci_path/iommu_group)))"; lsusb -s "$(cat "${usb_ctrl}/busnum"):"; echo; done</nowiki>|<br />
Bus 1 --> 0000:00:1a.0 (IOMMU group 4)<br />
Bus 001 Device 004: ID 04f2:b217 Chicony Electronics Co., Ltd Lenovo Integrated Camera (0.3MP)<br />
Bus 001 Device 007: ID 0a5c:21e6 Broadcom Corp. BCM20702 Bluetooth 4.0 [ThinkPad]<br />
Bus 001 Device 008: ID 0781:5530 SanDisk Corp. Cruzer<br />
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub<br />
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub<br />
<br />
Bus 2 --> 0000:00:1d.0 (IOMMU group 9)<br />
Bus 002 Device 006: ID 0451:e012 Texas Instruments, Inc. TI-Nspire Calculator<br />
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub<br />
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub}}<br />
<br />
This laptop has 3 USB ports managed by 2 USB controllers, each with their own IOMMU group. In this example, Bus 001 manages a single USB port (with a SanDisk USB pendrive plugged into it so it appears on the list), but also a number of internal devices, such as the internal webcam and the bluetooth card. Bus 002, on the other hand, does not apprear to manage anything except for the calculator that is plugged into it. The third port is empty, which is why it does not show up on the list, but is actually managed by Bus 002.<br />
<br />
Once you have identified which controller manages which ports by plugging various devices into them and decided which one you want to passthrough, simply add it to the list of PCI host devices controlled by the VM in your guest configuration. No other configuration should be needed.<br />
<br />
===Passing VM audio to host via PulseAudio===<br />
It is possible to route the virtual machine's audio to the host as an application using libvirt. This has the advantage of multiple audio streams being routable to one host output, and working with audio output devices that do not support passthrough. [[PulseAudio]] is required for this to work.<br />
<br />
First, remove the comment from the {{ic|<nowiki>#user = ""</nowiki>}} line. Then add your username in the quotations. This tells QEMU which user's pulseaudio stream to route through.<br />
{{hc|/etc/libvirt/qemu.conf|<br />
user <nowiki>=</nowiki> "example"}}<br />
<br />
Next, modify the libvirt configuration<br />
<br />
{{hc|EDITOR<nowiki>=</nowiki>nano virsh edit [vmname]|<br />
<domain type<nowiki>=</nowiki>'kvm'><br />
}}<br />
<br />
to<br />
<br />
{{hc|EDITOR<nowiki>=</nowiki>nano virsh edit [vmname]|<br />
<domain type<nowiki>=</nowiki>'kvm' xmlns:qemu<nowiki>='http://libvirt.org/schemas/domain/qemu/1.0'</nowiki>><br />
}}<br />
<br />
Then set the QEMU PulseAudio environment variables at the bottom of the libvirt xml file<br />
<br />
{{hc|EDITOR<nowiki>=</nowiki>nano virsh edit [vmname]|<br />
</devices><br />
</domain><br />
}}<br />
<br />
to<br />
<br />
{{hc|EDITOR<nowiki>=</nowiki>nano virsh edit [vmname]|<br />
</devices><br />
<qemu:commandline><br />
<qemu:env name<nowiki>=</nowiki>'QEMU_AUDIO_DRV' value<nowiki>=</nowiki>'pa'/><br />
<qemu:env name<nowiki>=</nowiki>'QEMU_PA_SERVER' value<nowiki>=</nowiki>'/run/user/1000/pulse/native'/><br />
</qemu:commandline><br />
</domain><br />
}}<br />
<br />
Change 1000 under the user directory to your user uid (which can be found by running the {{ic|id}} command.<br />
<br />
Restart libvirt and pulseaudio (run as your user)<br />
<br />
{{hc|systemctl restart libvirtd |<br />
pulseaudio --kill<br />
pulseaudio --start<br />
}}<br />
<br />
Virtual Machine audio will now be routed through the host as an application. The application {{Pkg|pavucontrol}} can be used to control the output device. Be aware that on Windows guests, this can cause audio crackling without [[#Slowed down audio pumped through HDMI on the video card|using Message-Signaled Interrupts.]]<br />
<br />
===Gotchas===<br />
====Passing through a device that does not support resetting====<br />
When the VM shuts down, all devices used by the guest are deinitialized by its OS in preparation for shutdown. In this state, those devices are no longer functionnal and must then be power-cycled before they can resume normal operation. Linux can handle this power-cycling on its own, but when a device has no known reset methods, it remains in this disabled state and becomes unavailable. Since Libvirt and Qemu both expect all host PCI devices to be ready to reattach to the host before completely stopping the VM, when encountering a device that won't reset, they will hang in a "Shutting down" state where they will not be able to be restarted until the host system has been rebooted. It is therefore reccomanded to only pass through PCI devices which the kernel is able to reset, as evidenced by the presence of a {{ic|reset}} file in the PCI device sysfs node, such as {{ic|/sys/bus/pci/devices/0000:00:1a.0/reset}}.<br />
<br />
The following bash command shows which devices can and cannot be reset.<br />
<br />
{{hc|<nowiki>for iommu_group in $(find /sys/kernel/iommu_groups/ -maxdepth 1 -mindepth 1 -type d);do echo "IOMMU group $(basename "$iommu_group")"; for device in $(\ls -1 "$iommu_group"/devices/); do if [[ -e "$iommu_group"/devices/"$device"/reset ]]; then echo -n "[RESET]"; fi; echo -n $'\t';lspci -nns "$device"; done; done</nowiki>|<br />
IOMMU group 0<br />
00:00.0 Host bridge [0600]: Intel Corporation Xeon E3-1200 v2/Ivy Bridge DRAM Controller [8086:0158] (rev 09)<br />
IOMMU group 1<br />
00:01.0 PCI bridge [0604]: Intel Corporation Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port [8086:0151] (rev 09)<br />
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation GK208 [GeForce GT 720] [10de:1288] (rev a1)<br />
01:00.1 Audio device [0403]: NVIDIA Corporation GK208 HDMI/DP Audio Controller [10de:0e0f] (rev a1)<br />
IOMMU group 2<br />
00:14.0 USB controller [0c03]: Intel Corporation 7 Series/C210 Series Chipset Family USB xHCI Host Controller [8086:1e31] (rev 04)<br />
IOMMU group 4<br />
[RESET] 00:1a.0 USB controller [0c03]: Intel Corporation 7 Series/C210 Series Chipset Family USB Enhanced Host Controller #2 [8086:1e2d] (rev 04)<br />
IOMMU group 5<br />
[RESET] 00:1b.0 Audio device [0403]: Intel Corporation 7 Series/C210 Series Chipset Family High Definition Audio Controller [8086:1e20] (rev 04)<br />
IOMMU group 10<br />
[RESET] 00:1d.0 USB controller [0c03]: Intel Corporation 7 Series/C210 Series Chipset Family USB Enhanced Host Controller #1 [8086:1e26] (rev 04)<br />
IOMMU group 13<br />
06:00.0 VGA compatible controller [0300]: NVIDIA Corporation GM204 [GeForce GTX 970] [10de:13c2] (rev a1)<br />
06:00.1 Audio device [0403]: NVIDIA Corporation GM204 High Definition Audio Controller [10de:0fbb] (rev a1)<br />
}}<br />
<br />
This signals that the xHCI USB controller in 00:14.0 cannot be reset and will therefore stop the VM from shutting down properly, while the integrated sound card in 00:1b.0 and the other two controllers in 00:1a.0 and 00:1d.0 do not share this problem and can be passed without issue.<br />
<br />
== Troubleshooting ==<br />
<br />
==="Error 43 : Driver failed to load" on Nvidia GPUs passed to Windows VMs===<br />
{{Note|This may also fix SYSTEM_THREAD_EXCEPTION_NOT_HANDLED boot crashes related to Nvidia drivers}}<br />
<br />
Since version 337.88, Nvidia drivers on Windows check if an hypervisor is running and fail if it detects one, which results in an Error 43 in the Windows device manager. Starting with QEMU 2.5.0 and libvirt 1.3.3, the vendor_id for the hypervisor can be spoofed, which is enough to fool the Nvidia drivers into loading anyway. All one must do is add {{ic|<nowiki>hv_vendor_id=whatever</nowiki>}} to the cpu parameters in their QEMU command line, or by adding the following line to their libvirt domain configuration. It may help for the ID to be set to a 12-character alphanumeric (e.g. '123456789ab') as opposed to longer or shorter strings.<br />
<br />
{{hc|<nowiki>EDITOR=nano virsh edit myPciPassthroughVm</nowiki>|...<br />
<nowiki><br />
<features><br />
<hyperv><br />
...<br />
<vendor_id state='on' value='whatever'/><br />
...<br />
</hyperv><br />
...<br />
<kvm><br />
<hidden state='on'/><br />
</kvm><br />
</features><br />
...<br />
</nowiki>}}<br />
<br />
Users with older versions of QEMU and/or libvirt will instead have to disable a few hypervisor extensions, which can degrade performance substentially. If this is what you want to do, do the following replacement in your libvirt domain config file.<br />
{{hc|<nowiki>EDITOR=nano virsh edit myPciPassthroughVm</nowiki>|...<br />
<nowiki><features><br />
<hyperv><br />
<relaxed state='on'/><br />
<vapic state='on'/><br />
<spinlocks state='on' retries='8191'/><br />
</hyperv><br />
...<br />
</features><br />
...<br />
<clock offset='localtime'><br />
<timer name='hypervclock' present='yes'/><br />
</clock></nowiki><br />
...}}<br />
{{bc|<nowiki>...<br />
<br />
<clock offset='localtime'><br />
<timer name='hypervclock' present='no'/><br />
</clock><br />
...<br />
<features><br />
<kvm><br />
<hidden state='on'/><br />
</kvm><br />
...<br />
<hyperv><br />
<relaxed state='off'/><br />
<vapic state='off'/><br />
<spinlocks state='off'/><br />
</hyperv><br />
...<br />
</features><br />
...</nowiki>}}<br />
<br />
===Unexpected crashes related to CPU exceptions===<br />
In some cases, kvm may react strangely to certain CPU operations, such as GeForce Experience complaining about an unsupported CPU being present or some game crashing for unknown reasons. A number of those issues can be solved by passing the {{ic|1=ignore_msrs=1}} option to the KVM module, which will ignore unimplemented MSRs instead of returning an error value.<br />
<br />
{{hc|<nowiki>/etc/modprobe.d/kvm.conf</nowiki>|<nowiki>...<br />
options kvm ignore_msrs=1<br />
...</nowiki>}}<br />
<br />
{{Warning|While this is normally safe and some applications might not work without this, silently ignoring unknown MSR accesses could potentially break other software within the VM or other VMs.}}<br />
<br />
==="System Thread Exception Not Handled" when booting on a Windows VM===<br />
Windows 8 or Windows 10 guests may raise a generic compatibility exception at boot, namely "System Thread Exception Not Handled", which tends to be caused by legacy drivers acting strangely on real machines. On KVM machines this issue can generally be solved by setting the CPU model to {{ic|core2duo}}.<br />
<br />
===Slowed down audio pumped through HDMI on the video card===<br />
For some users VM's audio slows down/starts stuttering/becomes demonic after a while when it's pumped through HDMI on the video card. This usually also slows down graphics.<br />
A possible solution consists of enabling MSI (Message Signaled-Based Interrupts) instead of the default (Line-Based Interrupts).<br />
<br />
In order to check whether MSI is supported or enabled, run the following command as root:<br />
# lspci -vs $device | grep 'MSI:'<br />
where `$device` is the card's address (e.g. `01:00.0`).<br />
<br />
The output should be similar to:<br />
Capabilities: [60] MSI: Enable'''-''' Count=1/1 Maskable- 64bit+<br />
<br />
A {{ic|-}} after {{ic|Enabled}} means MSI is supported, but not used by the VM, while a {{ic|+}} says that the VM is using it.<br />
<br />
The procedure to enable it is quite complex, instructions and an overview of the setting can be found [http://forums.guru3d.com/showthread.php?t=378044 here].<br />
<br />
Other hints can be found on the [http://lime-technology.com/wiki/index.php/UnRAID_6/VM_Guest_Support#Enable_MSI_for_Interrupts_to_Fix_HDMI_Audio_Support lime-technology's wiki], or on this article on [http://vfio.blogspot.it/2014/09/vfio-interrupts-and-how-to-coax-windows.html VFIO tips and tricks].<br />
<br />
Some tools named {{ic|MSI_util}} or similar are available on the Internet, but they didn't work for me on Windows 10 64bit.<br />
<br />
In order to fix the issues enabling MSI on the 0 function of my nVidia card ({{ic|01:00.0 VGA compatible controller: NVIDIA Corporation GM206 [GeForce GTX 960] (rev a1) (prog-if 00 [VGA controller])}}) was not enough; I also enabled it on the other function ({{ic|01:00.1 Audio device: NVIDIA Corporation Device 0fba (rev a1)}}) and that seems to have fixed the issue.<br />
<br />
<br />
=== No HDMI audio output on host when intel_iommu is enabled ===<br />
<br />
If after enabling {{ic|intel_iommu}} the HDMI output device of Intel GPU becomes unusable on the host then setting the option {{ic|igfx_off}} (i.e. {{ic|intel_iommu<nowiki>=</nowiki>on,igfx_off}}) might bring the audio back, please read {{ic|Graphics Problems?}} in [https://www.kernel.org/doc/Documentation/Intel-IOMMU.txt Intel-IOMMU.txt] for details about setting {{ic|igfx_off}}.<br />
<br />
== See also ==<br />
* [https://bbs.archlinux.org/viewtopic.php?id=162768 Discussion on Arch Linux forums] | [https://archive.is/kZYMt Archived link]<br />
* [https://docs.google.com/spreadsheet/ccc?key=0Aryg5nO-kBebdFozaW9tUWdVd2VHM0lvck95TUlpMlE User contributed hardware compatibility list]<br />
* [http://pastebin.com/rcnUZCv7 Example script from https://www.youtube.com/watch?v=37D2bRsthfI]<br />
* [http://vfio.blogspot.com/ Complete tutorial for PCI passthrough]<br />
* [https://www.redhat.com/archives/vfio-users/ VFIO users mailing list]<br />
* [https://webchat.freenode.net/?channels=vfio-users #vfio-users on freenode]</div>Stbinanhttps://wiki.archlinux.org/index.php?title=PCI_passthrough_via_OVMF&diff=473226PCI passthrough via OVMF2017-04-07T11:40:27Z<p>Stbinan: /* Troubleshooting */ Move to the bottom</p>
<hr />
<div>[[Category:Virtualization]]<br />
[[ja:OVMF による PCI パススルー]]<br />
The Open Virtual Machine Firmware ([http://www.tianocore.org/ovmf/ OVMF]) is a project to enable UEFI support for virtual machines. Starting with Linux 3.9 and recent versions of QEMU, it is now possible to passthrough a graphics card, offering the VM native graphics performance which is useful for graphic-intensive tasks.<br />
<br />
Provided you have a desktop computer with a spare GPU you can dedicate to the host (be it an integrated GPU or an old OEM card, the brands do not even need to match) and that your hardware supports it (see [[#Prerequisites]]), it is possible to have a VM of any OS with its own dedicated GPU and near-native performance. For more information on techniques see the background [http://www.linux-kvm.org/images/b/b3/01x09b-VFIOandYou-small.pdf presentation (pdf)]. <br />
<br />
== Prerequisites ==<br />
A VGA Passthrough relies on a number of technologies that are not ubiquitous as of today and might not be available on your hardware. You will not be able to do this on your machine unless the following requirements are met :<br />
<br />
* Your CPU must support hardware virtualization (for kvm) and IOMMU (for the passthrough itself)<br />
** [http://ark.intel.com/search/advanced?s=t&VTX=true&VTD=true List of compatible Intel CPUs (Intel VT-x and Intel VT-d)]<br />
** [http://support.amd.com/en-us/kb-articles/Pages/GPU120AMDRVICPUsHyperVWin8.aspx List of compatible AMD CPUs (AMD-V and AMD-Vi)]<br />
* Your motherboard must also support IOMMU<br />
** Both the chipset and the BIOS must support it. It is not always easy to tell at a glance whether or not this is the case, but there is a [http://wiki.xen.org/wiki/VTdHowTo fairly comprehensive list on the matter on the Xen wiki] as well as [[wikipedia:List_of_IOMMU-supporting_hardware|another one on Wikipedia]].<br />
* Your guest GPU ROM must support UEFI<br />
** If you can find [https://www.techpowerup.com/vgabios/ any ROM in this list] that applies to your specific GPU and is said to support UEFI, you are generally in the clear. All GPUs from 2012 and later should support this, as Microsoft made UEFI a requirement for devices to be marketed as compatible with Windows 8.<br />
<br />
You will probably want to have a spare monitor (the GPU will not display anything if there is no screen plugged in and using a VNC or Spice connection will not help your performance), as well as a mouse and a keyboard you can pass to your VM. If anything goes wrong, you will at least have a way to control your host machine this way.<br />
<br />
==Setting up IOMMU==<br />
IOMMU is a system specific IO mapping mechanism and can be used with most devices. IOMMU is a generic name for Intel VT-x/Intel and AMD AMD-V/AMD-Vi.<br />
===Enabling IOMMU===<br />
Ensure that AMD-VI/VT-d is enabled in your BIOS settings. Both normally show up alongside other CPU features (meaning they could be in an overclocking-related menu) either with their actual names ("Vt-d" or "AMD-VI"), legacy names ("Vanderpool" for Vt-x, "Pacifica" for AMD-V) or in more ambiguous terms such as "Virtualization technology", which may or may not be explained in the manual.<br />
<br />
You will also have to enable iommu support in the kernel itself through a [[Kernel_parameters|bootloader kernel option]]. Depending on your type of CPU, use either {{ic|intel_iommu<nowiki>=</nowiki>on}} for Intel CPUs (VT-d) or {{ic|amd_iommu<nowiki>=</nowiki>on}} for AMD CPUs (AMD-Vi).<br />
<br />
After rebooting, check dmesg to confirm that IOMMU has been correctly enabled:<br />
{{hc|dmesg<nowiki>|</nowiki>grep -e DMAR -e IOMMU|<br />
[ 0.000000] ACPI: DMAR 0x00000000BDCB1CB0 0000B8 (v01 INTEL BDW 00000001 INTL 00000001)<br />
[ 0.000000] Intel-IOMMU: enabled<br />
[ 0.028879] dmar: IOMMU 0: reg_base_addr fed90000 ver 1:0 cap c0000020660462 ecap f0101a<br />
[ 0.028883] dmar: IOMMU 1: reg_base_addr fed91000 ver 1:0 cap d2008c20660462 ecap f010da<br />
[ 0.028950] IOAPIC id 8 under DRHD base 0xfed91000 IOMMU 1<br />
[ 0.536212] DMAR: No ATSR found<br />
[ 0.536229] IOMMU 0 0xfed90000: using Queued invalidation<br />
[ 0.536230] IOMMU 1 0xfed91000: using Queued invalidation<br />
[ 0.536231] IOMMU: Setting RMRR:<br />
[ 0.536241] IOMMU: Setting identity map for device 0000:00:02.0 [0xbf000000 - 0xcf1fffff]<br />
[ 0.537490] IOMMU: Setting identity map for device 0000:00:14.0 [0xbdea8000 - 0xbdeb6fff]<br />
[ 0.537512] IOMMU: Setting identity map for device 0000:00:1a.0 [0xbdea8000 - 0xbdeb6fff]<br />
[ 0.537530] IOMMU: Setting identity map for device 0000:00:1d.0 [0xbdea8000 - 0xbdeb6fff]<br />
[ 0.537543] IOMMU: Prepare 0-16MiB unity mapping for LPC<br />
[ 0.537549] IOMMU: Setting identity map for device 0000:00:1f.0 [0x0 - 0xffffff]<br />
[ 2.182790] [drm] DMAR active, disabling use of stolen memory}}<br />
<br />
===Ensuring that the groups are valid===<br />
<br />
The following script should allow you to see how your various PCI devices are mapped to IOMMU groups. If it does not return anything, you either have not enabled IOMMU support properly or your hardware does not support it.<br />
<br />
#!/bin/bash<br />
shopt -s nullglob<br />
for d in /sys/kernel/iommu_groups/*/devices/*; do <br />
n=${d#*/iommu_groups/*}; n=${n%%/*}<br />
printf 'IOMMU Group %s ' "$n"<br />
lspci -nns "${d##*/}"<br />
done;<br />
<br />
Example output:<br />
<br />
IOMMU Group 0 00:00.0 Host bridge [0600]: Intel Corporation 2nd Generation Core Processor Family DRAM Controller [8086:0104] (rev 09)<br />
IOMMU Group 1 00:16.0 Communication controller [0780]: Intel Corporation 6 Series/C200 Series Chipset Family MEI Controller #1 [8086:1c3a] (rev 04)<br />
IOMMU Group 2 00:19.0 Ethernet controller [0200]: Intel Corporation 82579LM Gigabit Network Connection [8086:1502] (rev 04)<br />
IOMMU Group 3 00:1a.0 USB controller [0c03]: Intel Corporation 6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 [8086:1c2d] (rev <br />
...<br />
An IOMMU group is the smallest set of physical devices that can be passed to a virtual machine. For instance, in the example above, both the GPU in 06:00.0 and its audio controller in 6:00.1 belong to IOMMU group 13 and can only be passed together. The frontal USB controller, however, has its own group (group 2) which is separate from both the USB expansion controller (group 10) and the rear USB controller (group 4), meaning that [[#USB_controller|any of them could be passed to a VM without affecting the others]].<br />
<br />
===Gotchas===<br />
====Plugging your guest GPU in an unisolated CPU-based PCIe slot====<br />
Not all PCI-E slots are the same. Most motherboards have PCIe slots provided by both the CPU and the PCH. Depending on your CPU, it is possible that your processor-based PCIe slot does not support isolation properly, in which case the PCI slot itself will be appear to be grouped with the device that is connected to it.<br />
<br />
IOMMU Group 1 00:01.0 PCI bridge: Intel Corporation Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port (rev 09)<br />
IOMMU Group 1 01:00.0 VGA compatible controller: NVIDIA Corporation GM107 [GeForce GTX 750] (rev a2)<br />
IOMMU Group 1 01:00.1 Audio device: NVIDIA Corporation Device 0fbc (rev a1)<br />
<br />
This is fine so long as only your guest GPU is included in here, such as above. Depending on what is plugged in your other PCIe slots and whether they are allocated to your CPU or your PCH, you may find yourself with additional devices within the same group, which would force you to pass those as well. If you are ok with passing everything that is in there to your VM, you are free to continue. Otherwise, you will either need to try and plug your GPU in your other PCIe slots (if you have any) and see if those provide isolation from the rest or to install the ACS override patch, which comes with its own drawbacks. See [[#Bypassing the IOMMU groups (ACS override patch)]] for more information.<br />
<br />
{{note|If they are grouped with other devices in this manner, pci root ports and bridges should neither be bound to vfio at boot, nor be added to the VM.}}<br />
<br />
==Isolating the GPU==<br />
Due to their size and complexity, GPU drivers do not tend to support dynamic rebinding very well, so you cannot just have some GPU you use on the host be transparently passed to a VM without consequences. It is generally preferable to bind them with a placeholder driver instead. This will stop other drivers from attempting to claim it, and will force the GPU to remain inactive while a VM is not running. There are two methods for doing this, but it is recommended to use vfio-pci if your kernel supports it.<br />
<br />
{{warning|Once you reboot after this procedure, whatever GPU you have configured will no longer be usable on the host until you reverse the manipulation. Make sure the GPU you intend to use on the host is properly configured before doing this.}}<br />
<br />
===Using vfio-pci===<br />
Starting with Linux 4.1, the kernel includes vfio-pci, which is functionally similar to pci-stub with a few added bonuses, such as switching devices into their D3 state when they are not in use. If your system supports it, which you can try by running the following command, you should use it. If it returns en error, you will have to rely on pci-stub instead.<br />
<br />
{{hc|$ modinfo vfio-pci|<br />
filename: /lib/modules/4.4.5-1-ARCH/kernel/drivers/vfio/pci/vfio-pci.ko.gz<br />
description: VFIO PCI - User Level meta-driver<br />
author: Alex Williamson <alex.williamson@redhat.com><br />
...}}<br />
<br />
Vfio-pci normally targets PCI devices by ID, meaning you only need to specify the IDs of the devices you intend to passthrough. For the following IOMMU group, you would want to bind vfio-pci with {{ic|10de:13c2}} and {{ic|10de:0fbb}}, which will be used as example values for the rest of this section.<br />
<br />
IOMMU Group 13 06:00.0 VGA compatible controller: NVIDIA Corporation GM204 [GeForce GTX 970] [10de:13c2] (rev a1)<br />
IOMMU Group 13 06:00.1 Audio device: NVIDIA Corporation GM204 High Definition Audio Controller [10de:0fbb] (rev a1)}}<br />
<br />
{{note|You cannot specify which device to isolate using vendor-device ID pairs if the host GPU and the guest GPU share the same pair (i.e : if both are the same model). If this is your case, read the [[#Using_identical_guest_and_host_GPUs|Special procedures]] section instead.}}<br />
<br />
You can then add those vendor-device ID pairs to the default parameters passed to vfio-pci whenever it is inserted into the kernel.<br />
{{hc|1=/etc/modprobe.d/vfio.conf|2=options vfio-pci ids=10de:13c2,10de:0fbb}}<br />
{{note|If, as noted [[#Plugging_your_guest_GPU_in_an_unisolated_CPU-based_PCIe_slot|here]], your pci root port is part of your IOMMU group, you '''must not''' pass its ID to {{ic|vfio-pci}}, as it needs to remain attached to the host to function properly. Any other device within that group, however, should be left for {{ic|vfio-pci}} to bind with.}}<br />
<br />
This, however, does not guarantee that vfio-pci will be loaded before other graphics drivers. To ensure that, we need to statically bind it in the kernel image alongside with its dependencies. That means adding, in this order, {{ic|vfio}}, {{ic|vfio_iommu_type1}}, {{ic|vfio_pci}} and {{ic|vfio_virqfd}} to [[mkinitcpio]]:<br />
<br />
{{hc|1=/etc/mkinitcpio.conf|2=MODULES="... vfio vfio_iommu_type1 vfio_pci vfio_virqfd ..."}}<br />
<br />
{{note|If you also have another driver loaded this way for [[Kernel_mode_setting#Early_KMS_start|early modesetting]] (such as "nouveau", "radeon", "amdgpu", "i915", etc.), all of the aforementioned VFIO modules must precede it.}}<br />
<br />
Also, ensure that the modconf hook is included in the HOOKS list of mkinitcpio.conf:<br />
<br />
{{hc|1=/etc/mkinitcpio.conf|2=HOOKS="... modconf ..."}}<br />
<br />
Since new modules have been added to the initramfs configuration, it must be regenerated. Should you change the IDs of the devices in {{ic|/etc/modprobe.d/vfio.conf}}, you will also have to regenerate it, as those parameters must be specified in the initramfs to be known during the early boot stages.<br />
{{bc|# mkinitcpio -p linux}}<br />
{{Note|If you are using a non-standard kernel, such as {{ic|linux-vfio}}, replace {{ic|linux}} with whichever kernel you intend to use.}}<br />
<br />
Reboot and verify that vfio-pci has loaded properly and that it is now bound to the right devices.<br />
{{hc|$ dmesg <nowiki>|</nowiki> grep -i vfio |<br />
[ 0.329224] VFIO - User Level meta-driver version: 0.3<br />
[ 0.341372] vfio_pci: add [10de:13c2[ffff:ffff]] class 0x000000/00000000<br />
[ 0.354704] vfio_pci: add [10de:0fbb[ffff:ffff]] class 0x000000/00000000<br />
[ 2.061326] vfio-pci 0000:06:00.0: enabling device (0100 -> 0103)}}<br />
<br />
It isn't necessary for all devices (or even expected device) from vfio.conf to be in dmesg output. Sometimes device doesn't appear in output at boot but actually is able to be visible and operatable in guest VM.<br />
<br />
{{hc|$ lspci -nnk -d 10de:13c2|<br />
06:00.0 VGA compatible controller: NVIDIA Corporation GM204 [GeForce GTX 970] [10de:13c2] (rev a1)<br />
Kernel driver in use: vfio-pci<br />
Kernel modules: nouveau nvidia}}<br />
<br />
{{hc|$ lspci -nnk -d 10de:0fbb|<br />
06:00.1 Audio device: NVIDIA Corporation GM204 High Definition Audio Controller [10de:0fbb] (rev a1)<br />
Kernel driver in use: vfio-pci<br />
Kernel modules: snd_hda_intel}}<br />
<br />
===Using pci-stub (legacy method, pre-4.1 kernels)===<br />
If your kernel does not support vfio-pci, you can use the pci-stub module instead.<br />
<br />
Pci-stub normally targets PCI devices by ID, meaning you only need to specify the IDs of the devices you intend to passthrough. For the following IOMMU group, you would want to bind vfio-pci with {{ic|10de:13c2}} and {{ic|10de:0fbb}}, which will be used as example values for the rest of this section.<br />
<br />
IOMMU group 13 06:00.0 VGA compatible controller: NVIDIA Corporation GM204 [GeForce GTX 970] [10de:13c2] (rev a1)<br />
IOMMU group 13 06:00.1 Audio device: NVIDIA Corporation GM204 High Definition Audio Controller [10de:0fbb] (rev a1)}}<br />
<br />
{{note|You cannot specify which device to isolate using vendor-device ID pairs if the host GPU and the guest GPU share the same pair (i.e : if both are the same model). If this is your case, read the [[#Using_identical_guest_and_host_GPUs|Special procedures]] section instead.}}<br />
Most linux distros (including Arch Linux) have pci-stub built statically within the kernel image. If for any reason it needs to be loaded as a module in your case, you will need to bind it yourself using whatever tool your distro provides for this, such as {{ic|mkinitpcio}} for Arch.<br />
{{hc|<nowiki>/etc/mkinitcpio.conf</nowiki>|<nowiki>MODULES="... pci-stub ..."</nowiki>}}<br />
<br />
If you did need to add this module to your kernel image configuration manually, you must also regenerate it.<br />
{{bc|# mkinitcpio -p linux}}<br />
{{Note|If you are using a non-standard kernel, such as {{ic|linux-vfio}}, replace {{ic|linux}} with whichever kernel you intend to use.}}<br />
<br />
Add the relevant PCI device IDs to the kernel command line:<br />
{{hc|<nowiki>/etc/default/grub</nowiki>|<nowiki>...<br />
GRUB_CMDLINE_LINUX_DEFAULT="... pci-stub.ids=10de:13c2,10de:0fbb ..."<br />
...</nowiki>}}<br />
{{note|If, as noted [[#Plugging_your_guest_GPU_in_an_unisolated_CPU-based_PCIe_slot|here]], your pci root port is part of your IOMMU group, you '''must not''' pass its ID to {{ic|pci-stub}}, as it needs to remain attached to the host to function properly. Any other device within that group, however, should be left for {{ic|pci-stub}} to bind with.}}<br />
<br />
Reload the grub configuration:<br />
{{bc|# grub-mkconfig -o /boot/grub/grub.cfg}}<br />
<br />
Check dmesg output for successful assignment of the device to pci-stub:<br />
{{hc|dmesg <nowiki>|</nowiki> grep pci-stub|<br />
[ 2.390128] pci-stub: add 10DE:13C2 sub<nowiki>=</nowiki>FFFFFFFF:FFFFFFFF cls<nowiki>=</nowiki>00000000/00000000<br />
[ 2.390143] pci-stub 0000:06:00.0: claimed by stub<br />
[ 2.390150] pci-stub: add 10DE:0FBB sub<nowiki>=</nowiki>FFFFFFFF:FFFFFFFF cls<nowiki>=</nowiki>00000000/00000000<br />
[ 2.390159] pci-stub 0000:06:00.1: claimed by stub}}<br />
<br />
==Setting up an OVMF-based guest VM==<br />
OVMF is an open-source UEFI firmware for QEMU virtual machines. While it's possible to use SeaBIOS to get similar results to an actual PCI passthough, the setup process is different and it is generally preferable to use the EFI method if your hardware supports it.<br />
<br />
===Configuring libvirt===<br />
[[Libvirt]] is a wrapper for a number of virtualization utilities that greatly simplifies the configuration and deployment process of virtual machines. In the case of KVM and QEMU, the frontend it provides allows us to avoid dealing with the permissions for QEMU and make it easier to add and remove various devices on a live VM. Its status as a wrapper, however, means that it might not always support all of the latest qemu features, which could end up requiring the use of a wrapper script to provide some extra arguments to QEMU.<br />
<br />
After installing {{Pkg|qemu}}, {{Pkg|libvirt}}, {{AUR|ovmf-git}} and {{Pkg|virt-manager}}, add the path to your OVMF firmware image and runtime variables template to your libvirt config so {{ic|virt-install}} or {{ic|virt-manager}} can find those later on.<br />
<br />
{{hc|/etc/libvirt/qemu.conf|<br />
<nowiki>nvram = [</nowiki><br />
"/usr/share/ovmf/x64/ovmf_x64.bin:/usr/share/ovmf/x64/ovmf_vars_x64.bin"<br />
]<br />
}}<br />
<br />
You can now [[enable]] and start {{ic|libvirtd}} and its logging component.<br />
<br />
{{bc|<br />
# systemctl enable --now libvirtd<br />
# systemctl enable virtlogd.socket}}<br />
<br />
===Setting up the guest OS===<br />
The process of setting up a VM using {{ic|virt-manager}} is mostly self explainatory, as most of the process comes with fairly comprehensive on-screen instructions. However, you should pay special attention to the following steps :<br />
* When the VM creation wizard asks you to name your VM, check the "Customize before install" checkbox.<br />
* In the "Overview" section, set your firmware to "UEFI". If the option is grayed out, make sure that you have correctly specified the location of your firmware in {{ic|/etc/libvirt/qemu.conf}} and restart {{ic|libvirtd.service}}.<br />
* In the "CPUs" section, change your CPU model to "host-passthrough". If it is not in the list, you will have to type it by hand. This will ensure that your CPU is detected properly, since it causes libvirt to expose your CPU capabilities exactly as they are instead of only those it recognizes (which is the preferred default behavior to make CPU behavior easier to reproduce). Without it, some applications may complain about your CPU being of an unknown model.<br />
* If you want to minimize IO overhead, go into "Add Hardware" and add a Controller for SCSI drives of the "VirtIO SCSI" model. You can then change the default IDE disk for a SCSI disk, which will bind to said controller.<br />
** Windows VMs will not recognize those drives by default, so you need to download the ISO containing the drivers from [https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/latest-virtio/ here] and add an IDE (or SATA for Windows 8.1 and newer) CD-ROM storage device linking to said ISO, otherwise you will not be able to get Windows to recognize it during the installation process. When prompted to select a disk to install windows on, load the drivers contained on the CD-ROM under ''vioscsi''.<br />
<br />
The rest of the installation process will take place as normal using a standard QXL video adapter running in a window. At this point, there is no need to install additional drivers for the rest of the virtual devices, since most of them will be removed later on. Once the guest OS is done installing, simply turn off the virtual machine.<br />
<br />
===Attaching the PCI devices===<br />
With the installation done, it's now possible to edit the hardware details in libvirt and remove virtual integration devices, such as the spice channel and virtual display, the QXL video adapter, the emulated mouse and keyboard and the USB tablet device. Since that leaves you with no input devices, you may want to bind a few USB host devices to your VM as well, but remember to '''leave at least one mouse and/or keyboard assigned to your host''' in case something goes wrong with the guest. At this point, it also becomes possible to attach the PCI device that was isolated earlier; simply click on "Add Hardware" and select the PCI Host Devices you want to passthrough. If everything went well, the screen plugged into your GPU should show the OVMF splash screen and your VM should start up normally. From there, you can setup the drivers for the rest of your VM.<br />
<br />
===Gotchas===<br />
====Using a non-EFI image on an OVMF-based VM====<br />
The OVMF firmware does not support booting off non-EFI mediums. If the installation process drops you in a UEFI shell right after booting, you may have an invalid EFI boot media. Try using an alternate linux/windows image to determine if you have an invalid media.<br />
<br />
==Performance tuning==<br />
Most use cases for PCI passthroughs relate to performance-intensive domains such as video games and GPU-accelerated tasks. While a PCI passthrough on its own is a step towards reaching native performance, there are still a few ajustments on the host and guest to get the most out of your VM.<br />
<br />
===CPU pinning===<br />
The default behavior for KVM guests is to run operations coming from the guest as a number of threads representing virtual processors. Those threads are managed by the Linux scheduler like any other thread and are dispatched to any available CPU cores based on niceness and priority queues. Since switching between threads adds a bit of overhead (because context switching forces the core to change its cache between operations), this can noticeably harm performance on the guest. CPU pinning aims to resolve this as it overrides process scheduling and ensures that the VM threads will always run and only run on those specific cores. Here, for instance, the guest cores 0, 1, 2 and 3 are mapped to the host cores 4, 5, 6 and 7 respectively.<br />
<br />
{{hc|<nowiki>EDITOR=nano virsh edit myPciPassthroughVm</nowiki>|...<br />
<nowiki><vcpu placement='static'>4</vcpu><br />
<cputune><br />
<vcpupin vcpu='0' cpuset='4'/><br />
<vcpupin vcpu='1' cpuset='5'/><br />
<vcpupin vcpu='2' cpuset='6'/><br />
<vcpupin vcpu='3' cpuset='7'/><br />
</cputune></nowiki><br />
...}}<br />
<br />
====The case of Hyper-threading====<br />
If your CPU supports hardware multitasking, also known as Hyper-threading on Intel chips, there are two ways you can go with your CPU pinning. That is, Hyper-threading is simply a very efficient way of running two threads on one CPU at any given time, so while it may give you 8 logical cores on what would otherwise be a quad-core CPU, if the physical core is overloaded, the logical core won't be of any use. One could pin their VM threads on 2 physical cores and their 2 respective threads, but any task overloading those two cores won't be helped by the extra two logical cores, since in the end you're only passing through two cores out of four, not four out of eight. What you should do knowing this depends on what you intend to do with your host while your VM is running.<br />
<br />
This is the abridged content of {{ic|/proc/cpuinfo}} on a quad-core machine with hyper-threading.<br />
{{hc|<nowiki>$ cat /proc/cpuinfo | grep -e "processor" -e "core id" -e "^$"</nowiki>|<br />
processor : 0<br />
core id : 0<br />
<br />
processor : 1<br />
core id : 1<br />
<br />
processor : 2<br />
core id : 2<br />
<br />
processor : 3<br />
core id : 3<br />
<br />
processor : 4<br />
core id : 0<br />
<br />
processor : 5<br />
core id : 1<br />
<br />
processor : 6<br />
core id : 2<br />
<br />
processor : 7<br />
core id : 3}}<br />
<br />
If you don't intend to be doing any computation-heavy work on the host (or even anything at all) at the same time as you would on the VM, it would probably be better to pin your VM threads across all of your logical cores, so that the VM can fully take advantage of the spare CPU time on all your cores.<br />
<br />
On the quad-core machine mentioned above, it would look like this :<br />
{{hc|<nowiki>EDITOR=nano virsh edit myPciPassthroughVm</nowiki>|...<br />
<nowiki><vcpu placement='static'>4</vcpu><br />
<cputune><br />
<vcpupin vcpu='0' cpuset='4'/><br />
<vcpupin vcpu='1' cpuset='5'/><br />
<vcpupin vcpu='2' cpuset='6'/><br />
<vcpupin vcpu='3' cpuset='7'/><br />
</cputune><br />
...<br />
<cpu mode='custom' match='exact'><br />
...<br />
<topology sockets='1' cores='4' threads='1'/><br />
...<br />
</cpu></nowiki><br />
...}}<br />
<br />
If you would instead prefer to have the host and guest running intensive tasks at the same time, it would then be preferable to pin a limited amount of physical cores and their respective threads on the guest and leave the rest to the host to avoid the two competing for CPU time.<br />
<br />
On the quad-core machine mentioned above, it would look like this :<br />
{{hc|<nowiki>EDITOR=nano virsh edit myPciPassthroughVm</nowiki>|...<br />
<nowiki><vcpu placement='static'>4</vcpu><br />
<cputune><br />
<vcpupin vcpu='0' cpuset='2'/><br />
<vcpupin vcpu='1' cpuset='3'/><br />
<vcpupin vcpu='2' cpuset='6'/><br />
<vcpupin vcpu='3' cpuset='7'/><br />
</cputune><br />
...<br />
<cpu mode='custom' match='exact'><br />
...<br />
<topology sockets='1' cores='2' threads='2'/><br />
...<br />
</cpu></nowiki><br />
...}}<br />
<br />
===Static huge pages===<br />
When dealing with applications that require large amounts of memory, memory latency can become a problem since the more memory pages are being used, the more likely it is that this application will attempt to access information accross multiple memory "pages", which is the base unit for memory allocation. Resolving the actual address of the memory page takes multiple steps, and so CPUs normally cache information on recently used memory pages to make subsequent uses on the same pages faster. Applications using large amounts of memory run into a problem where, for instance, a virtual machine uses 4GB of memory divided into 4kB pages (which is the default size for normal pages), meaning that such cache misses can become extremely frequent and greatly increase memory latency. Huge pages exist to mitigate this issue by giving larger individual pages to those applications, increasing the odds that multiple operations will target the same page in succession. This is normally handeled with transparent huge pages, which dynamically manages hugepages to keep up with the demand.<br />
<br />
On a VM with a PCI passthrough, however, it is '''not possible''' to benefit from transparent huge pages, as IOMMU requires that the guest's memory be allocated and pinned as soon as the VM starts. It is therefore required to allocate huge pages statically in order to benefit from them. <br />
<br />
{{warning|Do note that static huge pages lock down the allocated amount of memory, making it unavailable for applications that are not configured to use them. Allocating 4GBs worth of huge pages on a machine with 8GBs of memory will only leave you with 4GBs of available memory on the host '''even when the VM is not running'''.}}<br />
<br />
To allocate huge pages at boot, one must simply specify the desired amount on their kernel comand line with {{ic|<nowiki>hugepages=x</nowiki>}}. For instance, reserving 1024 pages with {{ic|<nowiki>hugepages=1024</nowiki>}} and the default size of 2048kB per huge page creates 2GBs worth of memory for the virtual machine to use.<br />
<br />
Also, since static huge pages can only be used by applications that specifically request it, you must add this section in your libvirt domain configuration to allow kvm to benefit from them :<br />
{{hc|<nowiki>EDITOR=nano virsh edit myPciPassthroughVm</nowiki>|...<br />
<memoryBacking><br />
<hugepages/><br />
</memoryBacking><br />
...}}<br />
<br />
=== CPU frequency governor ===<br />
<br />
Depending on the way your [[CPU_frequency_scaling|CPU governor]] is configured, the VM threads may not hit the CPU load thresholds for the frequency to ramp up. Indeed, KVM cannot actually change the CPU frequency on its own, which can be a problem if the it does not scale up with vCPU usage as it would result in underwhelming performance. An easy way to see if it behaves correctly is to check if the frequency reported by {{ic|watch lscpu}} goes up when running a CPU-intensive task on the guest. If you are indeed experiencing stutter and the frequency does not go up to reach its reported maximum, it may be due to [https://lime-technology.com/forum/index.php?topic=46664.msg447678#msg447678 cpu scaling being controlled by the host OS]. In this case, try setting all cores to maximum frequency to see if this improves performance. Note that if you're using a modern intel chip with the default pstate driver, cpupower commands will be [[CPU_frequency_scaling#CPU_frequency_driver|ineffective]], so monitor {{ic|/proc/cpuinfo}} to make sure your cpu is actually at max frequency.<br />
<br />
=== High DPC Latency ===<br />
{{Accuracy|As far as I can tell all virtio modules listed here are for virtual devices used when Linux runs as a guest. Loading them on the host serves no purpose.}}<br />
If you are experiencing high DPC and/or interrupt latency in your Guest VM, ensure you have [[Kernel_modules#Manual_module_handling|loaded the needed virtio kernel modules]] on the host kernel. Loadable virtio kernel modules include: {{ic|virtio-pci, virtio-net, virtio-blk, virtio-balloon, virtio-ring}} and {{ic|virtio}}. <br />
<br />
After loading one or more of these modules, {{ic|lsmod <nowiki>|</nowiki> grep virtio}} executed on the host should not return empty.<br />
<br />
== Special procedures ==<br />
<br />
Certain setups require specific configuration tweaks in order to work properly. If you're having problems getting your host or your VM to work properly, see if your system matches one of the cases below and try adjusting your configuration accordingly.<br />
<br />
=== Using identical guest and host GPUs ===<br />
{{Expansion|A number of users have been having issues with this, it should probably be adressed by the article.|Talk:PCI passthrough via OVMF#Additionnal_sections}}<br />
Due to how both pci-stub and vfio-pci use your vendor and device id pair to identify which device they need to bind to at boot, if you have two GPUs sharing such an ID pair you won't be able to get your passthough driver to bind with just one of them. This sort of setup makes it necessary to use a script, so that whichever driver you're using is instead assigned by pci bus address using the {{ic|driver_override}} mechanism.<br />
<br />
Here, we will make a script to bind vfio-pci to all GPUs but the boot gpu. Create the script "/sbin/vfio-pci-override.sh":<br />
<br />
#!/bin/sh<br />
<br />
for i in /sys/devices/pci*/*/boot_vga; do<br />
if [ $(cat "$i") -eq 0 ]; then<br />
GPU="${i%/boot_vga}"<br />
AUDIO="$(echo "$GPU" | sed -e "s/0$/1/")"<br />
echo "vfio-pci" > "$GPU/driver_override"<br />
if [ -d "$AUDIO" ]; then<br />
echo "vfio-pci" > "$AUDIO/driver_override"<br />
fi<br />
fi<br />
done<br />
<br />
modprobe -i vfio-pci<br />
<br />
Create /etc/modprobe.d/vfio.conf with the following:<br />
install vfio-pci /sbin/vfio-pci-override.sh<br />
<br />
Edit /etc/mkinitcpio.conf<br />
<br />
Remove any video drivers from MODULES, and add vfio-pci, and vfio_iommu_type1<br />
MODULES="ext4 vfat vfio-pci vfio_iommu_type1"<br />
<br />
Add "/etc/modprobe.d/vfio.conf" and "/sbin/vfio-pci-override.sh" to FILES:<br />
FILES="/etc/modprobe.d/vfio.conf /sbin/vfio-pci-override.sh"<br />
<br />
Regenerate your initramfs, and reboot:<br />
mkinitcpio -p linux<br />
<br />
=== Passing the boot GPU to the guest ===<br />
{{Expansion|Not possible at the time as far as I'm aware, but a common issue on various forums.|Talk:PCI passthrough via OVMF#Additionnal_sections}}<br />
The GPU marked as {{ic|boot_vga}} is a special case when it comes to doing PCI passthroughs, since the BIOS needs to use it in order to display things like boot messages or the BIOS configuration menu. To do that, it makes [https://www.redhat.com/archives/vfio-users/2016-May/msg00224.html a copy of the VGA boot ROM which can then be freely modified]. This modified copy is the version the system gets to see, which the passthrough driver may reject as invalid. As such, it is generally reccomanded to change the boot GPU in the BIOS configuration so the host GPU is used instead or, if that's not possible, to swap the host and guest cards in the machine itself.<br />
<br />
=== Bypassing the IOMMU groups (ACS override patch) ===<br />
<br />
If you find your PCI devices grouped among others that you do not wish to pass through, you may be able to seperate them using Alex Williamson's ACS override patch. Make sure you understand [http://vfio.blogspot.com/2014/08/iommu-groups-inside-and-out.html the potential risk] of doing so. <br />
<br />
You will need a kernel with the patch applied. The easiest method to acquiring this is through the {{AUR|linux-vfio}} package. <br />
<br />
In addition, the ACS override patch needs to be enabled with kernel command line options. The patch file adds the following documentation:<br />
<br />
pcie_acs_override =<br />
[PCIE] Override missing PCIe ACS support for:<br />
downstream<br />
All downstream ports - full ACS capabilties<br />
multifunction<br />
All multifunction devices - multifunction ACS subset<br />
id:nnnn:nnnn<br />
Specfic device - full ACS capabilities<br />
Specified as vid:did (vendor/device ID) in hex<br />
<br />
The option {{ic|pcie_acs_override<nowiki>=</nowiki>downstream}} is typically sufficient.<br />
<br />
After installation and configuration, reconfigure your [[Kernel parameters|bootloader kernel parameters]] to load the new kernel with the {{ic|pcie_acs_override<nowiki>=</nowiki>}} option enabled.<br />
<br />
== QEMU without libvirtd (can switch GPUs without reboot) ==<br />
<br />
{{Remove|Too specific to warrant an article section. Some of the links could be moved to the [[#See also]] section.}}<br />
<br />
[https://git.mel.vin/melvin/scripts/tree/master/qemu] starts Samba and Synergy, runs the VM and closes everything after the VM is shut down. This method does '''not''' require libvirtd to be running or configured.<br />
<br />
With these new scripts, is it possible to switch GPUs without rebooting, only a restart of the X session is needed. This is all handled by a tiny shell script that runs in the tty. When you log in the tty, it will ask which card you would like to use if you autolaunch the shell script.<br />
<br />
[https://www.redhat.com/archives/vfio-users/2016-May/msg00187.html vfio-users : Full set of (runtime) scripts for VFIO + Qemu CLI]<br />
<br />
[https://www.redhat.com/archives/vfio-users/2015-August/msg00020.html vfio-users : Example configuration with CLI Qemu (working VM => host audio)]<br />
<br />
==Passing though other devices==<br />
===USB controller===<br />
If your motherboard has multiple USB controllers mapped to multiple groups, it is possible to pass those instead of USB devices. Passing an actual controller over an individual USB device provides the following advantages : <br />
<br />
* If a device disconnects or changes ID over the course of an given operation (such as a phone undergoing an update), the VM will not suddenly stop seeing it.<br />
* Any USB port managed by this controller is directly handled by the VM and can have its devices unplugged, replugged and changed without having to notify the hypervisor.<br />
* Libvirt will not complain if one of the USB devices you usually pass to the guest is missing when starting the VM.<br />
<br />
Unlike with GPUs, drivers for most USB controllers do not require any specific configuration to work on a VM and control can normally be passed back and forth between the host and guest systems with no side effects.<br />
<br />
{{Warning|Make sure your USB controller supports resetting :[[#Passing through a device that does not support resetting]]}}<br />
<br />
You can find out which PCI devices correspond to which controller and how various ports and devices are assigned to each one of them using this command :<br />
<br />
{{hc|$ <nowiki>for usb_ctrl in $(find /sys/bus/usb/devices/usb* -maxdepth 0 -type l); do pci_path="$(dirname "$(realpath "${usb_ctrl}")")"; echo "Bus $(cat "${usb_ctrl}/busnum") --> $(basename $pci_path) (IOMMU group $(basename $(realpath $pci_path/iommu_group)))"; lsusb -s "$(cat "${usb_ctrl}/busnum"):"; echo; done</nowiki>|<br />
Bus 1 --> 0000:00:1a.0 (IOMMU group 4)<br />
Bus 001 Device 004: ID 04f2:b217 Chicony Electronics Co., Ltd Lenovo Integrated Camera (0.3MP)<br />
Bus 001 Device 007: ID 0a5c:21e6 Broadcom Corp. BCM20702 Bluetooth 4.0 [ThinkPad]<br />
Bus 001 Device 008: ID 0781:5530 SanDisk Corp. Cruzer<br />
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub<br />
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub<br />
<br />
Bus 2 --> 0000:00:1d.0 (IOMMU group 9)<br />
Bus 002 Device 006: ID 0451:e012 Texas Instruments, Inc. TI-Nspire Calculator<br />
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub<br />
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub}}<br />
<br />
This laptop has 3 USB ports managed by 2 USB controllers, each with their own IOMMU group. In this example, Bus 001 manages a single USB port (with a SanDisk USB pendrive plugged into it so it appears on the list), but also a number of internal devices, such as the internal webcam and the bluetooth card. Bus 002, on the other hand, does not apprear to manage anything except for the calculator that is plugged into it. The third port is empty, which is why it does not show up on the list, but is actually managed by Bus 002.<br />
<br />
Once you have identified which controller manages which ports by plugging various devices into them and decided which one you want to passthrough, simply add it to the list of PCI host devices controlled by the VM in your guest configuration. No other configuration should be needed.<br />
<br />
===Passing VM audio to host via PulseAudio===<br />
It is possible to route the virtual machine's audio to the host as an application using libvirt. This has the advantage of multiple audio streams being routable to one host output, and working with audio output devices that do not support passthrough. [[PulseAudio]] is required for this to work.<br />
<br />
First, remove the comment from the {{ic|<nowiki>#user = ""</nowiki>}} line. Then add your username in the quotations. This tells QEMU which user's pulseaudio stream to route through.<br />
{{hc|/etc/libvirt/qemu.conf|<br />
user <nowiki>=</nowiki> "example"}}<br />
<br />
Next, modify the libvirt configuration<br />
<br />
{{hc|EDITOR<nowiki>=</nowiki>nano virsh edit [vmname]|<br />
<domain type<nowiki>=</nowiki>'kvm'><br />
}}<br />
<br />
to<br />
<br />
{{hc|EDITOR<nowiki>=</nowiki>nano virsh edit [vmname]|<br />
<domain type<nowiki>=</nowiki>'kvm' xmlns:qemu<nowiki>='http://libvirt.org/schemas/domain/qemu/1.0'</nowiki>><br />
}}<br />
<br />
Then set the QEMU PulseAudio environment variables at the bottom of the libvirt xml file<br />
<br />
{{hc|EDITOR<nowiki>=</nowiki>nano virsh edit [vmname]|<br />
</devices><br />
</domain><br />
}}<br />
<br />
to<br />
<br />
{{hc|EDITOR<nowiki>=</nowiki>nano virsh edit [vmname]|<br />
</devices><br />
<qemu:commandline><br />
<qemu:env name<nowiki>=</nowiki>'QEMU_AUDIO_DRV' value<nowiki>=</nowiki>'pa'/><br />
<qemu:env name<nowiki>=</nowiki>'QEMU_PA_SERVER' value<nowiki>=</nowiki>'/run/user/1000/pulse/native'/><br />
</qemu:commandline><br />
</domain><br />
}}<br />
<br />
Change 1000 under the user directory to your user uid (which can be found by running the {{ic|id}} command.<br />
<br />
Restart libvirt and pulseaudio (run as your user)<br />
<br />
{{hc|systemctl restart libvirtd |<br />
pulseaudio --kill<br />
pulseaudio --start<br />
}}<br />
<br />
Virtual Machine audio will now be routed through the host as an application. The application {{Pkg|pavucontrol}} can be used to control the output device. Be aware that on Windows guests, this can cause audio crackling without [[#Slowed down audio pumped through HDMI on the video card|using Message-Signaled Interrupts.]]<br />
<br />
===Gotchas===<br />
====Passing through a device that does not support resetting====<br />
When the VM shuts down, all devices used by the guest are deinitialized by its OS in preparation for shutdown. In this state, those devices are no longer functionnal and must then be power-cycled before they can resume normal operation. Linux can handle this power-cycling on its own, but when a device has no known reset methods, it remains in this disabled state and becomes unavailable. Since Libvirt and Qemu both expect all host PCI devices to be ready to reattach to the host before completely stopping the VM, when encountering a device that won't reset, they will hang in a "Shutting down" state where they will not be able to be restarted until the host system has been rebooted. It is therefore reccomanded to only pass through PCI devices which the kernel is able to reset, as evidenced by the presence of a {{ic|reset}} file in the PCI device sysfs node, such as {{ic|/sys/bus/pci/devices/0000:00:1a.0/reset}}.<br />
<br />
The following bash command shows which devices can and cannot be reset.<br />
<br />
{{hc|<nowiki>for iommu_group in $(find /sys/kernel/iommu_groups/ -maxdepth 1 -mindepth 1 -type d);do echo "IOMMU group $(basename "$iommu_group")"; for device in $(\ls -1 "$iommu_group"/devices/); do if [[ -e "$iommu_group"/devices/"$device"/reset ]]; then echo -n "[RESET]"; fi; echo -n $'\t';lspci -nns "$device"; done; done</nowiki>|<br />
IOMMU group 0<br />
00:00.0 Host bridge [0600]: Intel Corporation Xeon E3-1200 v2/Ivy Bridge DRAM Controller [8086:0158] (rev 09)<br />
IOMMU group 1<br />
00:01.0 PCI bridge [0604]: Intel Corporation Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port [8086:0151] (rev 09)<br />
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation GK208 [GeForce GT 720] [10de:1288] (rev a1)<br />
01:00.1 Audio device [0403]: NVIDIA Corporation GK208 HDMI/DP Audio Controller [10de:0e0f] (rev a1)<br />
IOMMU group 2<br />
00:14.0 USB controller [0c03]: Intel Corporation 7 Series/C210 Series Chipset Family USB xHCI Host Controller [8086:1e31] (rev 04)<br />
IOMMU group 4<br />
[RESET] 00:1a.0 USB controller [0c03]: Intel Corporation 7 Series/C210 Series Chipset Family USB Enhanced Host Controller #2 [8086:1e2d] (rev 04)<br />
IOMMU group 5<br />
[RESET] 00:1b.0 Audio device [0403]: Intel Corporation 7 Series/C210 Series Chipset Family High Definition Audio Controller [8086:1e20] (rev 04)<br />
IOMMU group 10<br />
[RESET] 00:1d.0 USB controller [0c03]: Intel Corporation 7 Series/C210 Series Chipset Family USB Enhanced Host Controller #1 [8086:1e26] (rev 04)<br />
IOMMU group 13<br />
06:00.0 VGA compatible controller [0300]: NVIDIA Corporation GM204 [GeForce GTX 970] [10de:13c2] (rev a1)<br />
06:00.1 Audio device [0403]: NVIDIA Corporation GM204 High Definition Audio Controller [10de:0fbb] (rev a1)<br />
}}<br />
<br />
This signals that the xHCI USB controller in 00:14.0 cannot be reset and will therefore stop the VM from shutting down properly, while the integrated sound card in 00:1b.0 and the other two controllers in 00:1a.0 and 00:1d.0 do not share this problem and can be passed without issue.<br />
<br />
== Troubleshooting ==<br />
<br />
=== No HDMI audio output on host when intel_iommu is enabled ===<br />
<br />
If after enabling {{ic|intel_iommu}} the HDMI output device of Intel GPU becomes unusable on the host then setting the option {{ic|igfx_off}} (i.e. {{ic|intel_iommu<nowiki>=</nowiki>on,igfx_off}}) might bring the audio back, please read {{ic|Graphics Problems?}} in [https://www.kernel.org/doc/Documentation/Intel-IOMMU.txt Intel-IOMMU.txt] for details about setting {{ic|igfx_off}}.<br />
<br />
== See also ==<br />
* [https://bbs.archlinux.org/viewtopic.php?id=162768 Discussion on Arch Linux forums] | [https://archive.is/kZYMt Archived link]<br />
* [https://docs.google.com/spreadsheet/ccc?key=0Aryg5nO-kBebdFozaW9tUWdVd2VHM0lvck95TUlpMlE User contributed hardware compatibility list]<br />
* [http://pastebin.com/rcnUZCv7 Example script from https://www.youtube.com/watch?v=37D2bRsthfI]<br />
* [http://vfio.blogspot.com/ Complete tutorial for PCI passthrough]<br />
* [https://www.redhat.com/archives/vfio-users/ VFIO users mailing list]<br />
* [https://webchat.freenode.net/?channels=vfio-users #vfio-users on freenode]</div>Stbinanhttps://wiki.archlinux.org/index.php?title=NVIDIA_Optimus&diff=468937NVIDIA Optimus2017-02-24T06:40:42Z<p>Stbinan: /* Disabling switchable graphics */ Find an internal page, so directly refer to it.</p>
<hr />
<div>[[Category:Graphics]]<br />
[[ja:NVIDIA Optimus]]<br />
[[ru:NVIDIA Optimus]]<br />
[[zh-hans:NVIDIA Optimus]]<br />
{{Related articles start}}<br />
{{Related|Bumblebee}}<br />
{{Related|Nouveau}}<br />
{{Related|NVIDIA}}<br />
{{Related articles end}}<br />
<br />
NVIDIA Optimus is a technology that allows an Intel integrated GPU and discrete NVIDIA GPU to be built into and accessed by a laptop. Getting Optimus graphics to work on Arch Linux requires a few somewhat complicated steps, explained below. There are several methods available:<br />
<br />
* disabling one of the devices in BIOS, which may result in improved battery life if the NVIDIA device is disabled, but may not be available with all BIOSes and does not allow GPU switching<br />
<br />
* using the official Optimus support included with the proprietary NVIDIA driver, which offers the best NVIDIA performance but does not allow GPU switching and can be more buggy than the open-source driver<br />
<br />
* using the PRIME functionality of the open-source nouveau driver, which allows GPU switching but offers poor performance compared to the proprietary NVIDIA driver and does not currently implement any powersaving<br />
<br />
* using the third-party Bumblebee program to implement Optimus-like functionality, which offers GPU switching and powersaving but requires extra configuration<br />
<br />
These options are explained in detail below.<br />
<br />
== Disabling switchable graphics ==<br />
<br />
If you only care to use a certain GPU without switching, check the options in your system's BIOS. There should be an option to disable one of the cards. Some laptops only allow disabling of the discrete card, or vice-versa, but it is worth checking if you only plan to use one of the cards.<br />
<br />
Another way is by using [https://www.archlinux.org/packages/community/x86_64/acpi_call/ acpi_call], for further information look at section "Fully Power Down Discrete GPU" at [[Hybrid graphics]]. [https://github.com/mkottman/acpi_call]<br />
<br />
If you want to use both cards, or cannot disable the card you do not want, see the options below.<br />
<br />
== Using nvidia ==<br />
<br />
The [[NVIDIA|proprietary NVIDIA driver]] does not support dynamic switching like the nouveau driver (meaning it can only use the NVIDIA device). It also has notable screen-tearing issues that NVIDIA recognizes but has not fixed. However, it does allow use of the discrete GPU and has (as of October 2013) a marked edge in performance over the nouveau driver.<br />
<br />
First, install {{Pkg|nvidia}}, {{Pkg|nvidia-libgl}} and {{Pkg|xorg-xrandr}} from the official repositories.<br />
<br />
Then, configure {{ic|xorg.conf}}. You will need to know the PCI address of the NVIDIA card, which you can find by issuing<br />
<br />
$ lspci | grep -E "VGA|3D"<br />
<br />
The PCI address is the first 7 characters of the line that mentions NVIDIA. It will look something like {{ic|01:00.0}}. In the {{ic|xorg.conf}}, you will need to format it as {{ic|#:#:#}}; e.g. {{ic|01:00.0}} would be formatted as {{ic|1:0:0}}.<br />
<br />
{{Note|Since Xorg-server 1.17-1 {{Bug|43830}} related to the {{ic|modesetting}} module persists for Optimus configurations. A work-around for some systems is to set the {{ic|Option "AccelMethod"}} to {{ic|"none"}}, as in the configuration below. Other systems require it set to {{ic|"sna"}}, see [[#Alternative configuration]].}}<br />
{{Note|On some setups this setup breaks automatic detection of the values of the display by the nvidia driver through the EDID file. As a work-around see [[#Resolution, screen scan wrong. EDID errors in Xorg.log]]. }}<br />
If X.Org X server version 1.17.2 or higher is installed ([http://us.download.nvidia.com/XFree86/Linux-x86/358.16/README/randr14.html])<br />
{{hc|/etc/X11/xorg.conf|<br />
Section "Module"<br />
Load "modesetting"<br />
EndSection<br />
<br />
Section "Device"<br />
Identifier "nvidia"<br />
Driver "nvidia"<br />
BusID "<BusID for NVIDIA device here>"<br />
Option "AllowEmptyInitialConfiguration"<br />
EndSection<br />
}}<br />
For older X servers<br />
{{hc|/etc/X11/xorg.conf|<br />
Section "ServerLayout"<br />
Identifier "layout"<br />
Screen 0 "nvidia"<br />
Inactive "intel"<br />
EndSection<br />
<br />
Section "Device"<br />
Identifier "nvidia"<br />
Driver "nvidia"<br />
'''# Change BusID if necessary. Tips: (lspci &#124; grep 3D) (Change 01:00.0 to 1:0:0)'''<br />
'''BusID "PCI:1:0:0"'''<br />
EndSection<br />
<br />
Section "Screen"<br />
Identifier "nvidia"<br />
Device "nvidia"<br />
Option "AllowEmptyInitialConfiguration" "Yes"<br />
EndSection<br />
<br />
Section "Device"<br />
Identifier "intel"<br />
Driver "modesetting"<br />
'''# Change BusID if necessary. Tips: (lspci &#124; grep VGA) (Change 00:02.0 to 0:2:0)'''<br />
'''BusID "PCI:0:2:0"'''<br />
Option "AccelMethod" "none"<br />
EndSection<br />
<br />
Section "Screen"<br />
Identifier "intel"<br />
Device "intel"<br />
EndSection<br />
<br />
}}<br />
<br />
Next, add the following two lines to the beginning of your {{ic|~/.xinitrc}}:<br />
<br />
{{hc|~/.xinitrc|<br />
xrandr --setprovideroutputsource modesetting NVIDIA-0<br />
xrandr --auto<br />
}}<br />
<br />
Now reboot to load the drivers, and X should start.<br />
<br />
If your display dpi is not correct add following line:<br />
<br />
xrandr --dpi 96<br />
<br />
If you get a black screen when starting X, make sure that there are no ampersands after the two {{ic|xrandr}} commands in {{ic|~/.xinitrc}}. If there are ampersands, it seems that the window manager can run before the {{ic|xrandr}} commands finish executing, leading to a black screen. <br />
<br />
If the black screen persists, see the [[#Alternative configuration]] below. <br />
<br />
=== Alternative configuration ===<br />
<br />
If you experience Xorg-server crashes since release 1.17.1 with above configuration, modify the section for the Intel device in {{ic|/etc/X11/xorg.conf}} as follows:<br />
<br />
{{hc|# nano /etc/X11/xorg.conf|<br />
Section "Device"<br />
Identifier "intel"<br />
Driver "modesetting"<br />
BusID "PCI:0:2:0"<br />
Option "AccelMethod" "sna"<br />
#Option "TearFree" "True"<br />
#Option "Tiling" "True"<br />
#Option "SwapbuffersWait" "True"<br />
EndSection}}<br />
<br />
As above, the {{ic|BusID}} must match for the output of the ''lspci'' command. Search for the line with "VGA compatible controller", that contains something Intel. For example: <br />
$ lspci |grep VGA<br />
00:02.0 VGA compatible controller: Intel Corporation Haswell-ULT Integrated Graphics Controller (rev 0b)<br />
<br />
{{Tip|The three last commented out options may (without #) result in positive effects on the tearing, but exchange for some performance cost. Note the {{ic|TearFree}} option may be used for {{ic|"sna"}} acceleration only, see [[Intel graphics]]. <br />
You can use either {{ic|"sna"}} or {{ic|"uxa"}} in {{ic|"AccelMethod"}} option. For further experimenting, a working {{ic|xorg.conf}} from a Lenovo Ideapad Z50-70 59-432128 is here: [http://pastebin.com/tMtPz381].}}<br />
<br />
If X starts but nothing appears on the screen, check if {{ic|/var/log/xorg.conf}} contains a following line or similar:<br />
<br />
{{hc|/var/log/xorg.conf|<br />
[ 16112.937] (EE) Screen 1 deleted because of no matching config section.<br />
}}<br />
<br />
If so, the problem may disappear when you change your ServerLayout section of {{ic|/etc/X11/xorg.conf}}:<br />
<br />
{{hc|/etc/X11/xorg.conf|<br />
Section "ServerLayout"<br />
Identifier "layout"<br />
Screen '''1''' "nvidia"<br />
Inactive "intel"<br />
EndSection<br />
}}<br />
<br />
=== Display Managers ===<br />
<br />
If you are using a display manager then you will need to create or edit a display setup script for your display manager instead of using {{ic|~/.xinitrc}}.<br />
<br />
==== LightDM ====<br />
<br />
For the [[LightDM]] display manager:<br />
<br />
{{hc|/etc/lightdm/display_setup.sh|<br />
#!/bin/sh<br />
xrandr --setprovideroutputsource modesetting NVIDIA-0<br />
xrandr --auto<br />
}}<br />
<br />
Make the script executable:<br />
<br />
# chmod +x /etc/lightdm/display_setup.sh<br />
<br />
Now configure lightdm to run the script by editing the {{ic|[Seat:*]}} section in {{ic|/etc/lightdm/lightdm.conf}}:<br />
<br />
{{hc|/etc/lightdm/lightdm.conf|output=<br />
[Seat:*]<br />
display-setup-script=/etc/lightdm/display_setup.sh<br />
}}<br />
<br />
Now reboot and your display manager should start.<br />
<br />
==== SDDM ====<br />
For the [[SDDM]] display manager:<br />
<br />
{{hc|/usr/share/sddm/scripts/Xsetup|<br />
xrandr --setprovideroutputsource modesetting NVIDIA-0<br />
xrandr --auto<br />
}}<br />
<br />
==== GDM ====<br />
<br />
For the [[GDM]] display manager create two new .desktop files:<br />
<br />
{{hc|/usr/share/gdm/greeter/autostart/optimus.desktop<br />
/etc/xdg/autostart/optimus.desktop|<br />
<nowiki>[Desktop Entry]<br />
Type=Application<br />
Name=Optimus<br />
Exec=sh -c "xrandr --setprovideroutputsource modesetting NVIDIA-0; xrandr --auto"<br />
NoDisplay=true<br />
X-GNOME-Autostart-Phase=DisplayServer</nowiki><br />
}}<br />
<br />
Make sure that GDM use [[GDM#Use_Xorg_backend|X as default backend]].<br />
<br />
==== KDM ====<br />
<br />
For KDE's [[KDM]], add the xrandr lines into {{ic|/usr/share/config/kdm/Xsetup}}.<br />
<br />
=== Checking 3D ===<br />
<br />
You can check if the NVIDIA graphics are being used by installing {{Pkg|mesa-demos}} and running<br />
<br />
$ glxinfo | grep NVIDIA<br />
<br />
=== Further Information ===<br />
<br />
For more information, look at NVIDIA's official page on the topic [http://us.download.nvidia.com/XFree86/Linux-x86/370.28/README/randr14.html].<br />
<br />
== Troubleshooting ==<br />
<br />
=== Tearing/Broken VSync ===<br />
<br />
This requires {{pkg|xorg-server}} 1.19 or higher, {{pkg|linux}} kernel 4.5 or higher, and {{pkg|nvidia}} 370.23 or higher. You can read the official [https://devtalk.nvidia.com/default/topic/957814/linux/prime-and-prime-synchronization/ forum thread here]. <br />
<br />
=== Failed to initialize the NVIDIA GPU at PCI:1:0:0 (GPU fallen off the bus / RmInitAdapter failed!) ===<br />
<br />
Add {{ic|1=rcutree.rcu_idle_gp_delay=1}} to the kernel parameters. Original topic can be found [https://bbs.archlinux.org/viewtopic.php?id=169742 here].<br />
<br />
=== Resolution, screen scan wrong. EDID errors in Xorg.log ===<br />
<br />
This is due to the NVIDIA driver not detecting the EDID for the display. You need to manually specify the path to an EDID file or provide the same information in a similar way.<br />
<br />
To provide the path to the EDID file edit the Device Section for the NVIDIA card in Xorg.conf, adding these lines and changing parts to reflect your own system:<br />
<br />
{{hc|/etc/X11/xorg.conf|<br />
Section "Device"<br />
Option "ConnectedMonitor" "CRT-0"<br />
Option "CustomEDID" "CRT-0:/sys/class/drm/card0-LVDS-1/edid"<br />
Option "IgnoreEDID" "false"<br />
Option "UseEDID" "true"<br />
EndSection<br />
}}<br />
<br />
If Xorg wont start try swapping out all references of CRT to DFB.<br />
card0 is the identifier for the intel card to which the display is connected via LVDS. The edid binary is in this directory. If the hardware arrangement is different, the value for CustomEDID might vary but yet this has to be confirmed. The path will start in any case with /sys/class/drm.<br />
<br />
Alternatively you can generate your edid with tools like {{Pkg|read-edid}} and point the driver to this file. Even modelines can be used, but then be sure to change "UseEDID" and "IgnoreEDID".<br />
<br />
=== Lockup issue (lspci hangs) ===<br />
Symptoms: lspci hangs, system suspend fails, shutdown hangs, optirun hangs.<br />
<br />
Applies to: newer laptops with GTX 965M or alike when bbswitch (e.g. via Bumblebee) or nouveau is in use.<br />
<br />
When the dGPU power resource is turned on, it may fail to do so and hang in ACPI code ([https://bugzilla.kernel.org/show_bug.cgi?id=156341 kernel bug 156341]).<br />
<br />
For known model-specific workarounds, see [https://github.com/Bumblebee-Project/Bumblebee/issues/764#issuecomment-234494238 this issue].<br />
In other cases you can try to boot with {{ic|1=acpi_osi="!Windows 2015"}} or {{ic|1=acpi_osi=! acpi_osi="Windows 2009"}} added to your [[Kernel parameters]]. (Consider reporting your laptop to that issue.)<br />
<br />
== Using nouveau ==<br />
<br />
The open-source [[nouveau]] driver ({{Pkg|xf86-video-nouveau}}) can dynamically switch with the Intel driver ({{Pkg|xf86-video-intel}}) using a technology called PRIME. For more information, see the wiki article on [[PRIME]].<br />
<br />
== Using Bumblebee ==<br />
<br />
If you wish to use Bumblebee, which will implement powersaving and some other useful features, see the wiki article on [[Bumblebee]].</div>Stbinanhttps://wiki.archlinux.org/index.php?title=NVIDIA_Optimus&diff=468936NVIDIA Optimus2017-02-24T06:22:39Z<p>Stbinan: /* Disabling switchable graphics */ typo</p>
<hr />
<div>[[Category:Graphics]]<br />
[[ja:NVIDIA Optimus]]<br />
[[ru:NVIDIA Optimus]]<br />
[[zh-hans:NVIDIA Optimus]]<br />
{{Related articles start}}<br />
{{Related|Bumblebee}}<br />
{{Related|Nouveau}}<br />
{{Related|NVIDIA}}<br />
{{Related articles end}}<br />
<br />
NVIDIA Optimus is a technology that allows an Intel integrated GPU and discrete NVIDIA GPU to be built into and accessed by a laptop. Getting Optimus graphics to work on Arch Linux requires a few somewhat complicated steps, explained below. There are several methods available:<br />
<br />
* disabling one of the devices in BIOS, which may result in improved battery life if the NVIDIA device is disabled, but may not be available with all BIOSes and does not allow GPU switching<br />
<br />
* using the official Optimus support included with the proprietary NVIDIA driver, which offers the best NVIDIA performance but does not allow GPU switching and can be more buggy than the open-source driver<br />
<br />
* using the PRIME functionality of the open-source nouveau driver, which allows GPU switching but offers poor performance compared to the proprietary NVIDIA driver and does not currently implement any powersaving<br />
<br />
* using the third-party Bumblebee program to implement Optimus-like functionality, which offers GPU switching and powersaving but requires extra configuration<br />
<br />
These options are explained in detail below.<br />
<br />
== Disabling switchable graphics ==<br />
<br />
If you only care to use a certain GPU without switching, check the options in your system's BIOS. There should be an option to disable one of the cards. Some laptops only allow disabling of the discrete card, or vice-versa, but it is worth checking if you only plan to use one of the cards.<br />
<br />
Another way is by using [https://www.archlinux.org/packages/community/x86_64/acpi_call/ acpi_call], after install the package, load the module with {{ic|modprobe acpi_call}}. Then you can test the turn_off_gpu script: {{ic|sh /usr/share/acpi_callexamples/turn_off_gpu.sh}}. If one parameter prints "works!", the discrete card should be turned off. [https://github.com/mkottman/acpi_call]<br />
<br />
If you want to use both cards, or cannot disable the card you do not want, see the options below.<br />
<br />
== Using nvidia ==<br />
<br />
The [[NVIDIA|proprietary NVIDIA driver]] does not support dynamic switching like the nouveau driver (meaning it can only use the NVIDIA device). It also has notable screen-tearing issues that NVIDIA recognizes but has not fixed. However, it does allow use of the discrete GPU and has (as of October 2013) a marked edge in performance over the nouveau driver.<br />
<br />
First, install {{Pkg|nvidia}}, {{Pkg|nvidia-libgl}} and {{Pkg|xorg-xrandr}} from the official repositories.<br />
<br />
Then, configure {{ic|xorg.conf}}. You will need to know the PCI address of the NVIDIA card, which you can find by issuing<br />
<br />
$ lspci | grep -E "VGA|3D"<br />
<br />
The PCI address is the first 7 characters of the line that mentions NVIDIA. It will look something like {{ic|01:00.0}}. In the {{ic|xorg.conf}}, you will need to format it as {{ic|#:#:#}}; e.g. {{ic|01:00.0}} would be formatted as {{ic|1:0:0}}.<br />
<br />
{{Note|Since Xorg-server 1.17-1 {{Bug|43830}} related to the {{ic|modesetting}} module persists for Optimus configurations. A work-around for some systems is to set the {{ic|Option "AccelMethod"}} to {{ic|"none"}}, as in the configuration below. Other systems require it set to {{ic|"sna"}}, see [[#Alternative configuration]].}}<br />
{{Note|On some setups this setup breaks automatic detection of the values of the display by the nvidia driver through the EDID file. As a work-around see [[#Resolution, screen scan wrong. EDID errors in Xorg.log]]. }}<br />
If X.Org X server version 1.17.2 or higher is installed ([http://us.download.nvidia.com/XFree86/Linux-x86/358.16/README/randr14.html])<br />
{{hc|/etc/X11/xorg.conf|<br />
Section "Module"<br />
Load "modesetting"<br />
EndSection<br />
<br />
Section "Device"<br />
Identifier "nvidia"<br />
Driver "nvidia"<br />
BusID "<BusID for NVIDIA device here>"<br />
Option "AllowEmptyInitialConfiguration"<br />
EndSection<br />
}}<br />
For older X servers<br />
{{hc|/etc/X11/xorg.conf|<br />
Section "ServerLayout"<br />
Identifier "layout"<br />
Screen 0 "nvidia"<br />
Inactive "intel"<br />
EndSection<br />
<br />
Section "Device"<br />
Identifier "nvidia"<br />
Driver "nvidia"<br />
'''# Change BusID if necessary. Tips: (lspci &#124; grep 3D) (Change 01:00.0 to 1:0:0)'''<br />
'''BusID "PCI:1:0:0"'''<br />
EndSection<br />
<br />
Section "Screen"<br />
Identifier "nvidia"<br />
Device "nvidia"<br />
Option "AllowEmptyInitialConfiguration" "Yes"<br />
EndSection<br />
<br />
Section "Device"<br />
Identifier "intel"<br />
Driver "modesetting"<br />
'''# Change BusID if necessary. Tips: (lspci &#124; grep VGA) (Change 00:02.0 to 0:2:0)'''<br />
'''BusID "PCI:0:2:0"'''<br />
Option "AccelMethod" "none"<br />
EndSection<br />
<br />
Section "Screen"<br />
Identifier "intel"<br />
Device "intel"<br />
EndSection<br />
<br />
}}<br />
<br />
Next, add the following two lines to the beginning of your {{ic|~/.xinitrc}}:<br />
<br />
{{hc|~/.xinitrc|<br />
xrandr --setprovideroutputsource modesetting NVIDIA-0<br />
xrandr --auto<br />
}}<br />
<br />
Now reboot to load the drivers, and X should start.<br />
<br />
If your display dpi is not correct add following line:<br />
<br />
xrandr --dpi 96<br />
<br />
If you get a black screen when starting X, make sure that there are no ampersands after the two {{ic|xrandr}} commands in {{ic|~/.xinitrc}}. If there are ampersands, it seems that the window manager can run before the {{ic|xrandr}} commands finish executing, leading to a black screen. <br />
<br />
If the black screen persists, see the [[#Alternative configuration]] below. <br />
<br />
=== Alternative configuration ===<br />
<br />
If you experience Xorg-server crashes since release 1.17.1 with above configuration, modify the section for the Intel device in {{ic|/etc/X11/xorg.conf}} as follows:<br />
<br />
{{hc|# nano /etc/X11/xorg.conf|<br />
Section "Device"<br />
Identifier "intel"<br />
Driver "modesetting"<br />
BusID "PCI:0:2:0"<br />
Option "AccelMethod" "sna"<br />
#Option "TearFree" "True"<br />
#Option "Tiling" "True"<br />
#Option "SwapbuffersWait" "True"<br />
EndSection}}<br />
<br />
As above, the {{ic|BusID}} must match for the output of the ''lspci'' command. Search for the line with "VGA compatible controller", that contains something Intel. For example: <br />
$ lspci |grep VGA<br />
00:02.0 VGA compatible controller: Intel Corporation Haswell-ULT Integrated Graphics Controller (rev 0b)<br />
<br />
{{Tip|The three last commented out options may (without #) result in positive effects on the tearing, but exchange for some performance cost. Note the {{ic|TearFree}} option may be used for {{ic|"sna"}} acceleration only, see [[Intel graphics]]. <br />
You can use either {{ic|"sna"}} or {{ic|"uxa"}} in {{ic|"AccelMethod"}} option. For further experimenting, a working {{ic|xorg.conf}} from a Lenovo Ideapad Z50-70 59-432128 is here: [http://pastebin.com/tMtPz381].}}<br />
<br />
If X starts but nothing appears on the screen, check if {{ic|/var/log/xorg.conf}} contains a following line or similar:<br />
<br />
{{hc|/var/log/xorg.conf|<br />
[ 16112.937] (EE) Screen 1 deleted because of no matching config section.<br />
}}<br />
<br />
If so, the problem may disappear when you change your ServerLayout section of {{ic|/etc/X11/xorg.conf}}:<br />
<br />
{{hc|/etc/X11/xorg.conf|<br />
Section "ServerLayout"<br />
Identifier "layout"<br />
Screen '''1''' "nvidia"<br />
Inactive "intel"<br />
EndSection<br />
}}<br />
<br />
=== Display Managers ===<br />
<br />
If you are using a display manager then you will need to create or edit a display setup script for your display manager instead of using {{ic|~/.xinitrc}}.<br />
<br />
==== LightDM ====<br />
<br />
For the [[LightDM]] display manager:<br />
<br />
{{hc|/etc/lightdm/display_setup.sh|<br />
#!/bin/sh<br />
xrandr --setprovideroutputsource modesetting NVIDIA-0<br />
xrandr --auto<br />
}}<br />
<br />
Make the script executable:<br />
<br />
# chmod +x /etc/lightdm/display_setup.sh<br />
<br />
Now configure lightdm to run the script by editing the {{ic|[Seat:*]}} section in {{ic|/etc/lightdm/lightdm.conf}}:<br />
<br />
{{hc|/etc/lightdm/lightdm.conf|output=<br />
[Seat:*]<br />
display-setup-script=/etc/lightdm/display_setup.sh<br />
}}<br />
<br />
Now reboot and your display manager should start.<br />
<br />
==== SDDM ====<br />
For the [[SDDM]] display manager:<br />
<br />
{{hc|/usr/share/sddm/scripts/Xsetup|<br />
xrandr --setprovideroutputsource modesetting NVIDIA-0<br />
xrandr --auto<br />
}}<br />
<br />
==== GDM ====<br />
<br />
For the [[GDM]] display manager create two new .desktop files:<br />
<br />
{{hc|/usr/share/gdm/greeter/autostart/optimus.desktop<br />
/etc/xdg/autostart/optimus.desktop|<br />
<nowiki>[Desktop Entry]<br />
Type=Application<br />
Name=Optimus<br />
Exec=sh -c "xrandr --setprovideroutputsource modesetting NVIDIA-0; xrandr --auto"<br />
NoDisplay=true<br />
X-GNOME-Autostart-Phase=DisplayServer</nowiki><br />
}}<br />
<br />
Make sure that GDM use [[GDM#Use_Xorg_backend|X as default backend]].<br />
<br />
==== KDM ====<br />
<br />
For KDE's [[KDM]], add the xrandr lines into {{ic|/usr/share/config/kdm/Xsetup}}.<br />
<br />
=== Checking 3D ===<br />
<br />
You can check if the NVIDIA graphics are being used by installing {{Pkg|mesa-demos}} and running<br />
<br />
$ glxinfo | grep NVIDIA<br />
<br />
=== Further Information ===<br />
<br />
For more information, look at NVIDIA's official page on the topic [http://us.download.nvidia.com/XFree86/Linux-x86/370.28/README/randr14.html].<br />
<br />
== Troubleshooting ==<br />
<br />
=== Tearing/Broken VSync ===<br />
<br />
This requires {{pkg|xorg-server}} 1.19 or higher, {{pkg|linux}} kernel 4.5 or higher, and {{pkg|nvidia}} 370.23 or higher. You can read the official [https://devtalk.nvidia.com/default/topic/957814/linux/prime-and-prime-synchronization/ forum thread here]. <br />
<br />
=== Failed to initialize the NVIDIA GPU at PCI:1:0:0 (GPU fallen off the bus / RmInitAdapter failed!) ===<br />
<br />
Add {{ic|1=rcutree.rcu_idle_gp_delay=1}} to the kernel parameters. Original topic can be found [https://bbs.archlinux.org/viewtopic.php?id=169742 here].<br />
<br />
=== Resolution, screen scan wrong. EDID errors in Xorg.log ===<br />
<br />
This is due to the NVIDIA driver not detecting the EDID for the display. You need to manually specify the path to an EDID file or provide the same information in a similar way.<br />
<br />
To provide the path to the EDID file edit the Device Section for the NVIDIA card in Xorg.conf, adding these lines and changing parts to reflect your own system:<br />
<br />
{{hc|/etc/X11/xorg.conf|<br />
Section "Device"<br />
Option "ConnectedMonitor" "CRT-0"<br />
Option "CustomEDID" "CRT-0:/sys/class/drm/card0-LVDS-1/edid"<br />
Option "IgnoreEDID" "false"<br />
Option "UseEDID" "true"<br />
EndSection<br />
}}<br />
<br />
If Xorg wont start try swapping out all references of CRT to DFB.<br />
card0 is the identifier for the intel card to which the display is connected via LVDS. The edid binary is in this directory. If the hardware arrangement is different, the value for CustomEDID might vary but yet this has to be confirmed. The path will start in any case with /sys/class/drm.<br />
<br />
Alternatively you can generate your edid with tools like {{Pkg|read-edid}} and point the driver to this file. Even modelines can be used, but then be sure to change "UseEDID" and "IgnoreEDID".<br />
<br />
=== Lockup issue (lspci hangs) ===<br />
Symptoms: lspci hangs, system suspend fails, shutdown hangs, optirun hangs.<br />
<br />
Applies to: newer laptops with GTX 965M or alike when bbswitch (e.g. via Bumblebee) or nouveau is in use.<br />
<br />
When the dGPU power resource is turned on, it may fail to do so and hang in ACPI code ([https://bugzilla.kernel.org/show_bug.cgi?id=156341 kernel bug 156341]).<br />
<br />
For known model-specific workarounds, see [https://github.com/Bumblebee-Project/Bumblebee/issues/764#issuecomment-234494238 this issue].<br />
In other cases you can try to boot with {{ic|1=acpi_osi="!Windows 2015"}} or {{ic|1=acpi_osi=! acpi_osi="Windows 2009"}} added to your [[Kernel parameters]]. (Consider reporting your laptop to that issue.)<br />
<br />
== Using nouveau ==<br />
<br />
The open-source [[nouveau]] driver ({{Pkg|xf86-video-nouveau}}) can dynamically switch with the Intel driver ({{Pkg|xf86-video-intel}}) using a technology called PRIME. For more information, see the wiki article on [[PRIME]].<br />
<br />
== Using Bumblebee ==<br />
<br />
If you wish to use Bumblebee, which will implement powersaving and some other useful features, see the wiki article on [[Bumblebee]].</div>Stbinanhttps://wiki.archlinux.org/index.php?title=NVIDIA_Optimus&diff=468935NVIDIA Optimus2017-02-24T06:21:53Z<p>Stbinan: /* Disabling switchable graphics */ add another method</p>
<hr />
<div>[[Category:Graphics]]<br />
[[ja:NVIDIA Optimus]]<br />
[[ru:NVIDIA Optimus]]<br />
[[zh-hans:NVIDIA Optimus]]<br />
{{Related articles start}}<br />
{{Related|Bumblebee}}<br />
{{Related|Nouveau}}<br />
{{Related|NVIDIA}}<br />
{{Related articles end}}<br />
<br />
NVIDIA Optimus is a technology that allows an Intel integrated GPU and discrete NVIDIA GPU to be built into and accessed by a laptop. Getting Optimus graphics to work on Arch Linux requires a few somewhat complicated steps, explained below. There are several methods available:<br />
<br />
* disabling one of the devices in BIOS, which may result in improved battery life if the NVIDIA device is disabled, but may not be available with all BIOSes and does not allow GPU switching<br />
<br />
* using the official Optimus support included with the proprietary NVIDIA driver, which offers the best NVIDIA performance but does not allow GPU switching and can be more buggy than the open-source driver<br />
<br />
* using the PRIME functionality of the open-source nouveau driver, which allows GPU switching but offers poor performance compared to the proprietary NVIDIA driver and does not currently implement any powersaving<br />
<br />
* using the third-party Bumblebee program to implement Optimus-like functionality, which offers GPU switching and powersaving but requires extra configuration<br />
<br />
These options are explained in detail below.<br />
<br />
== Disabling switchable graphics ==<br />
<br />
If you only care to use a certain GPU without switching, check the options in your system's BIOS. There should be an option to disable one of the cards. Some laptops only allow disabling of the discrete card, or vice-versa, but it is worth checking if you only plan to use one of the cards.<br />
<br />
Another way is by using [https://www.archlinux.org/packages/community/x86_64/acpi_call/ acpi_call], after install the package, load the module with {{ic|modprobe acpi_call}}. Then you can test the turn_off_gpu script: {{ic|sh /usr/share/acpi_callexamples/turn_off_gpu.sh}}. If one parameter print "works!", the discrete card should be turned off. [https://github.com/mkottman/acpi_call]<br />
<br />
If you want to use both cards, or cannot disable the card you do not want, see the options below.<br />
<br />
== Using nvidia ==<br />
<br />
The [[NVIDIA|proprietary NVIDIA driver]] does not support dynamic switching like the nouveau driver (meaning it can only use the NVIDIA device). It also has notable screen-tearing issues that NVIDIA recognizes but has not fixed. However, it does allow use of the discrete GPU and has (as of October 2013) a marked edge in performance over the nouveau driver.<br />
<br />
First, install {{Pkg|nvidia}}, {{Pkg|nvidia-libgl}} and {{Pkg|xorg-xrandr}} from the official repositories.<br />
<br />
Then, configure {{ic|xorg.conf}}. You will need to know the PCI address of the NVIDIA card, which you can find by issuing<br />
<br />
$ lspci | grep -E "VGA|3D"<br />
<br />
The PCI address is the first 7 characters of the line that mentions NVIDIA. It will look something like {{ic|01:00.0}}. In the {{ic|xorg.conf}}, you will need to format it as {{ic|#:#:#}}; e.g. {{ic|01:00.0}} would be formatted as {{ic|1:0:0}}.<br />
<br />
{{Note|Since Xorg-server 1.17-1 {{Bug|43830}} related to the {{ic|modesetting}} module persists for Optimus configurations. A work-around for some systems is to set the {{ic|Option "AccelMethod"}} to {{ic|"none"}}, as in the configuration below. Other systems require it set to {{ic|"sna"}}, see [[#Alternative configuration]].}}<br />
{{Note|On some setups this setup breaks automatic detection of the values of the display by the nvidia driver through the EDID file. As a work-around see [[#Resolution, screen scan wrong. EDID errors in Xorg.log]]. }}<br />
If X.Org X server version 1.17.2 or higher is installed ([http://us.download.nvidia.com/XFree86/Linux-x86/358.16/README/randr14.html])<br />
{{hc|/etc/X11/xorg.conf|<br />
Section "Module"<br />
Load "modesetting"<br />
EndSection<br />
<br />
Section "Device"<br />
Identifier "nvidia"<br />
Driver "nvidia"<br />
BusID "<BusID for NVIDIA device here>"<br />
Option "AllowEmptyInitialConfiguration"<br />
EndSection<br />
}}<br />
For older X servers<br />
{{hc|/etc/X11/xorg.conf|<br />
Section "ServerLayout"<br />
Identifier "layout"<br />
Screen 0 "nvidia"<br />
Inactive "intel"<br />
EndSection<br />
<br />
Section "Device"<br />
Identifier "nvidia"<br />
Driver "nvidia"<br />
'''# Change BusID if necessary. Tips: (lspci &#124; grep 3D) (Change 01:00.0 to 1:0:0)'''<br />
'''BusID "PCI:1:0:0"'''<br />
EndSection<br />
<br />
Section "Screen"<br />
Identifier "nvidia"<br />
Device "nvidia"<br />
Option "AllowEmptyInitialConfiguration" "Yes"<br />
EndSection<br />
<br />
Section "Device"<br />
Identifier "intel"<br />
Driver "modesetting"<br />
'''# Change BusID if necessary. Tips: (lspci &#124; grep VGA) (Change 00:02.0 to 0:2:0)'''<br />
'''BusID "PCI:0:2:0"'''<br />
Option "AccelMethod" "none"<br />
EndSection<br />
<br />
Section "Screen"<br />
Identifier "intel"<br />
Device "intel"<br />
EndSection<br />
<br />
}}<br />
<br />
Next, add the following two lines to the beginning of your {{ic|~/.xinitrc}}:<br />
<br />
{{hc|~/.xinitrc|<br />
xrandr --setprovideroutputsource modesetting NVIDIA-0<br />
xrandr --auto<br />
}}<br />
<br />
Now reboot to load the drivers, and X should start.<br />
<br />
If your display dpi is not correct add following line:<br />
<br />
xrandr --dpi 96<br />
<br />
If you get a black screen when starting X, make sure that there are no ampersands after the two {{ic|xrandr}} commands in {{ic|~/.xinitrc}}. If there are ampersands, it seems that the window manager can run before the {{ic|xrandr}} commands finish executing, leading to a black screen. <br />
<br />
If the black screen persists, see the [[#Alternative configuration]] below. <br />
<br />
=== Alternative configuration ===<br />
<br />
If you experience Xorg-server crashes since release 1.17.1 with above configuration, modify the section for the Intel device in {{ic|/etc/X11/xorg.conf}} as follows:<br />
<br />
{{hc|# nano /etc/X11/xorg.conf|<br />
Section "Device"<br />
Identifier "intel"<br />
Driver "modesetting"<br />
BusID "PCI:0:2:0"<br />
Option "AccelMethod" "sna"<br />
#Option "TearFree" "True"<br />
#Option "Tiling" "True"<br />
#Option "SwapbuffersWait" "True"<br />
EndSection}}<br />
<br />
As above, the {{ic|BusID}} must match for the output of the ''lspci'' command. Search for the line with "VGA compatible controller", that contains something Intel. For example: <br />
$ lspci |grep VGA<br />
00:02.0 VGA compatible controller: Intel Corporation Haswell-ULT Integrated Graphics Controller (rev 0b)<br />
<br />
{{Tip|The three last commented out options may (without #) result in positive effects on the tearing, but exchange for some performance cost. Note the {{ic|TearFree}} option may be used for {{ic|"sna"}} acceleration only, see [[Intel graphics]]. <br />
You can use either {{ic|"sna"}} or {{ic|"uxa"}} in {{ic|"AccelMethod"}} option. For further experimenting, a working {{ic|xorg.conf}} from a Lenovo Ideapad Z50-70 59-432128 is here: [http://pastebin.com/tMtPz381].}}<br />
<br />
If X starts but nothing appears on the screen, check if {{ic|/var/log/xorg.conf}} contains a following line or similar:<br />
<br />
{{hc|/var/log/xorg.conf|<br />
[ 16112.937] (EE) Screen 1 deleted because of no matching config section.<br />
}}<br />
<br />
If so, the problem may disappear when you change your ServerLayout section of {{ic|/etc/X11/xorg.conf}}:<br />
<br />
{{hc|/etc/X11/xorg.conf|<br />
Section "ServerLayout"<br />
Identifier "layout"<br />
Screen '''1''' "nvidia"<br />
Inactive "intel"<br />
EndSection<br />
}}<br />
<br />
=== Display Managers ===<br />
<br />
If you are using a display manager then you will need to create or edit a display setup script for your display manager instead of using {{ic|~/.xinitrc}}.<br />
<br />
==== LightDM ====<br />
<br />
For the [[LightDM]] display manager:<br />
<br />
{{hc|/etc/lightdm/display_setup.sh|<br />
#!/bin/sh<br />
xrandr --setprovideroutputsource modesetting NVIDIA-0<br />
xrandr --auto<br />
}}<br />
<br />
Make the script executable:<br />
<br />
# chmod +x /etc/lightdm/display_setup.sh<br />
<br />
Now configure lightdm to run the script by editing the {{ic|[Seat:*]}} section in {{ic|/etc/lightdm/lightdm.conf}}:<br />
<br />
{{hc|/etc/lightdm/lightdm.conf|output=<br />
[Seat:*]<br />
display-setup-script=/etc/lightdm/display_setup.sh<br />
}}<br />
<br />
Now reboot and your display manager should start.<br />
<br />
==== SDDM ====<br />
For the [[SDDM]] display manager:<br />
<br />
{{hc|/usr/share/sddm/scripts/Xsetup|<br />
xrandr --setprovideroutputsource modesetting NVIDIA-0<br />
xrandr --auto<br />
}}<br />
<br />
==== GDM ====<br />
<br />
For the [[GDM]] display manager create two new .desktop files:<br />
<br />
{{hc|/usr/share/gdm/greeter/autostart/optimus.desktop<br />
/etc/xdg/autostart/optimus.desktop|<br />
<nowiki>[Desktop Entry]<br />
Type=Application<br />
Name=Optimus<br />
Exec=sh -c "xrandr --setprovideroutputsource modesetting NVIDIA-0; xrandr --auto"<br />
NoDisplay=true<br />
X-GNOME-Autostart-Phase=DisplayServer</nowiki><br />
}}<br />
<br />
Make sure that GDM use [[GDM#Use_Xorg_backend|X as default backend]].<br />
<br />
==== KDM ====<br />
<br />
For KDE's [[KDM]], add the xrandr lines into {{ic|/usr/share/config/kdm/Xsetup}}.<br />
<br />
=== Checking 3D ===<br />
<br />
You can check if the NVIDIA graphics are being used by installing {{Pkg|mesa-demos}} and running<br />
<br />
$ glxinfo | grep NVIDIA<br />
<br />
=== Further Information ===<br />
<br />
For more information, look at NVIDIA's official page on the topic [http://us.download.nvidia.com/XFree86/Linux-x86/370.28/README/randr14.html].<br />
<br />
== Troubleshooting ==<br />
<br />
=== Tearing/Broken VSync ===<br />
<br />
This requires {{pkg|xorg-server}} 1.19 or higher, {{pkg|linux}} kernel 4.5 or higher, and {{pkg|nvidia}} 370.23 or higher. You can read the official [https://devtalk.nvidia.com/default/topic/957814/linux/prime-and-prime-synchronization/ forum thread here]. <br />
<br />
=== Failed to initialize the NVIDIA GPU at PCI:1:0:0 (GPU fallen off the bus / RmInitAdapter failed!) ===<br />
<br />
Add {{ic|1=rcutree.rcu_idle_gp_delay=1}} to the kernel parameters. Original topic can be found [https://bbs.archlinux.org/viewtopic.php?id=169742 here].<br />
<br />
=== Resolution, screen scan wrong. EDID errors in Xorg.log ===<br />
<br />
This is due to the NVIDIA driver not detecting the EDID for the display. You need to manually specify the path to an EDID file or provide the same information in a similar way.<br />
<br />
To provide the path to the EDID file edit the Device Section for the NVIDIA card in Xorg.conf, adding these lines and changing parts to reflect your own system:<br />
<br />
{{hc|/etc/X11/xorg.conf|<br />
Section "Device"<br />
Option "ConnectedMonitor" "CRT-0"<br />
Option "CustomEDID" "CRT-0:/sys/class/drm/card0-LVDS-1/edid"<br />
Option "IgnoreEDID" "false"<br />
Option "UseEDID" "true"<br />
EndSection<br />
}}<br />
<br />
If Xorg wont start try swapping out all references of CRT to DFB.<br />
card0 is the identifier for the intel card to which the display is connected via LVDS. The edid binary is in this directory. If the hardware arrangement is different, the value for CustomEDID might vary but yet this has to be confirmed. The path will start in any case with /sys/class/drm.<br />
<br />
Alternatively you can generate your edid with tools like {{Pkg|read-edid}} and point the driver to this file. Even modelines can be used, but then be sure to change "UseEDID" and "IgnoreEDID".<br />
<br />
=== Lockup issue (lspci hangs) ===<br />
Symptoms: lspci hangs, system suspend fails, shutdown hangs, optirun hangs.<br />
<br />
Applies to: newer laptops with GTX 965M or alike when bbswitch (e.g. via Bumblebee) or nouveau is in use.<br />
<br />
When the dGPU power resource is turned on, it may fail to do so and hang in ACPI code ([https://bugzilla.kernel.org/show_bug.cgi?id=156341 kernel bug 156341]).<br />
<br />
For known model-specific workarounds, see [https://github.com/Bumblebee-Project/Bumblebee/issues/764#issuecomment-234494238 this issue].<br />
In other cases you can try to boot with {{ic|1=acpi_osi="!Windows 2015"}} or {{ic|1=acpi_osi=! acpi_osi="Windows 2009"}} added to your [[Kernel parameters]]. (Consider reporting your laptop to that issue.)<br />
<br />
== Using nouveau ==<br />
<br />
The open-source [[nouveau]] driver ({{Pkg|xf86-video-nouveau}}) can dynamically switch with the Intel driver ({{Pkg|xf86-video-intel}}) using a technology called PRIME. For more information, see the wiki article on [[PRIME]].<br />
<br />
== Using Bumblebee ==<br />
<br />
If you wish to use Bumblebee, which will implement powersaving and some other useful features, see the wiki article on [[Bumblebee]].</div>Stbinanhttps://wiki.archlinux.org/index.php?title=OpenRC&diff=468823OpenRC2017-02-22T07:01:20Z<p>Stbinan: Add a tip</p>
<hr />
<div>[[Category:Boot process]]<br />
[[ja:OpenRC]]<br />
[[ru:OpenRC]]<br />
{{Related articles start}}<br />
{{Related|eudev}}<br />
{{Related|init}}<br />
{{Related|init Rosetta}}<br />
{{Related|SysVinit}}<br />
{{Related articles end}}<br />
{{Warning|Arch Linux only has official support for [[systemd]]. When using OpenRC, please mention so in support requests.}}<br />
<br />
[https://wiki.gentoo.org/wiki/OpenRC OpenRC] is a service manager maintained by the Gentoo developers. OpenRC is dependency based and works with the system provided init program, normally [[SysVinit]].<br />
<br />
== Installation ==<br />
<br />
OpenRC and accompanying packages are available in the [[AUR]]. For details on init components, see [[Init]].<br />
<br />
Install either the {{AUR|openrc}} or {{AUR|openrc-git}} package. {{AUR|openrc-sysvinit}} or {{Pkg|busybox}} are used as the init process. Service files are available from the {{AUR|openrc-arch-services-git}} package.<br />
<br />
{{Accuracy|{{AUR|openrc-sysvinit}} removes {{Pkg|systemd-sysvcompat}}}}<br />
<br />
To maintain compability with {{AUR|initscripts-fork}}, configuration files are installed to {{ic|'''/etc/openrc/'''}}. The sysvinit init binary is installed to {{ic|/usr/bin/init-openrc}} for compability with {{Pkg|systemd-sysvcompat}} or similar packages.<br />
<br />
=== Booting ===<br />
<br />
For booting with OpenRC add {{Ic|1=init=/usr/bin/init-openrc}} to the [[kernel parameters]]. To switch back to systemd, remove the parameter again.<br />
<br />
The {{Ic|1=/etc/openrc/conf.d}} directory, and the {{Ic|1=/etc/openrc/rc.d}} file is used for configuration.<br />
<br />
== Configuration ==<br />
<br />
For general information on configuring OpenRC, see:<br />
<br />
* [http://www.calculate-linux.org/main/en/openrc_manuals OpenRC manuals]<br />
* [http://www.gentoo.org/doc/en/openrc-migration.xml OpenRC migration]<br />
* [http://wiki.gentoo.org/wiki/OpenRC gentoo wiki]. <br />
<br />
=== Preparation ===<br />
<br />
See [[Init#Configuration]].<br />
<br />
=== Services ===<br />
<br />
OpenRC services are enabled by issuing {{ic|rc-update add ''service_name'' ''runlevel''}} as root. It is recommended to at least enable the following services:<br />
{| class="wikitable"<br />
! Service name<br />
! [https://wiki.gentoo.org/wiki/OpenRC#Named_runlevels Runlevel]<br />
! Description<br />
|-<br />
| udev<br />
| sysinit<br />
| Device hot-plugging<br />
|-<br />
| alsa<br />
| default<br />
| [[ALSA]] state<br />
|-<br />
| acpid<br />
| default<br />
| ACPI events<br />
|-<br />
| dbus<br />
| default<br />
| Messaging bus<br />
|-<br />
| dcron<br />
| default<br />
| Scheduling<br />
|-<br />
| syslog-ng<br />
| default<br />
| System logs<br />
|}<br />
<br />
See also [https://wiki.gentoo.org/wiki/Systemd#Native_services Native services] and [[Daemons]].<br />
<br />
=== Network ===<br />
<br />
The network is configured through {{ic|newnet}}. [https://github.com/funtoo/openrc/blob/master/README.newnet] Modify the {{ic|/etc/openrc/conf.d/network}} file; both the {{ic|ip}} ({{Pkg|iproute2}}) and the {{ic|ifconfig}} ({{Pkg|net-tools}}) commands are supported. Below is an example configuration using {{ic|ip}}.<br />
<br />
{{bc|<br />
<nowiki>ip_eth0="192.168.1.2/24"<br />
defaultiproute="via 192.168.1.1"<br />
ifup_eth0="ip link set \$int mtu 1500"<br />
</nowiki>}}<br />
<br />
The network service is added to the boot runlevel by default, so no further action is required. See [[Network configuration]] for general networking information.<br />
<br />
{{Note|1=You may also use [[NetworkManager]], [[dhcpcd]] or {{AUR|netcfg}} by enabling the respective services. ''netcfg'' mimics the [[netctl]] behaviour (see [https://bbs.archlinux.org/viewtopic.php?pid=1489283#p1489283] if you want to enable profiles connection on booting - requires {{ic|wpa_actiond}}). You could consult the [https://www.archlinux.org/netcfg/features.html official documentation] or [https://wiki.archlinux.org/index.php?title=Netcfg&oldid=243178 old wiki documentation] (be aware of consulting version later than [https://www.archlinux.org/news/netcfg-282-release/ 2012-05-13])}}<br />
<br />
=== Boot logs ===<br />
<br />
To enable boot logging, uncomment the {{ic|1=rc_logger="YES"}} line in {{ic|/etc/openrc/rc.conf}}. When enabled, boot logs are stored in {{ic|/var/log/rc.log}}.<br />
<br />
=== Hostname ===<br />
<br />
OpenRC sets the hostname from {{ic|/etc/openrc/conf.d/hostname}}. The file looks as follows:<br />
<br />
{{bc|# Set to the hostname of this machine<br />
hostname<nowiki>=</nowiki>"myhostname"}}<br />
<br />
=== Kernel modules ===<br />
<br />
OpenRC uses {{ic|/etc/openrc/conf.d/modules}} instead of {{ic|/etc/modules-load.d}}. For example:<br />
<br />
{{hc|/etc/openrc/conf.d/modules|2=<br />
# You should consult your kernel documentation and configuration<br />
# for a list of modules and their options.<br />
<br />
modules="vboxdrv acpi_cpufreq"<br />
}}<br />
<br />
=== Locale ===<br />
<br />
Keyboard layout can be configured via {{ic|/etc/openrc/conf.d/keymaps}} and {{ic|/etc/openrc/conf.d/consolefont}}. You can also configure the settings through the {{ic|/etc/locale.conf}} file, which is sourced via {{ic|/etc/profile.d/locale.sh}}. <br />
<br />
See [http://wiki.gentoo.org/wiki/Localization/HOWTO#Keyboard_layout_for_the_console] and [[Locale]] for details.<br />
<br />
=== DM-Crypt ===<br />
<br />
See [http://gentoo-en.vfose.ru/wiki/DM-Crypt DM-Crypt - Gentoo-en] for automatically mounting encrypted LVM or other block devices.<br />
<br />
== Tips and tricks ==<br />
<br />
=== Quiet booting ===<br />
<br />
To hide boot messages from OpenRC, you can edit {{ic|/etc/inittab}} and add {{ic|--quiet}} to every openrc command. For further information check with {{ic|$ openrc -h}}.<br />
<br />
== Troubleshooting ==<br />
<br />
=== Error while unmounting /tmp ===<br />
<br />
When shutting the system down, you might get an error message such as <br />
<br />
{{bc|* Unmounting /tmp ... <br />
* in use but fuser finds nothing [ !! ]}}<br />
<br />
This can be fixed by adding<br />
<br />
no_umounts="/tmp"<br />
<br />
to {{ic|/etc/openrc/conf.d/localmount}}<br />
<br />
{{Note|This problem occurs only if your tmp is mounted as a tmpfs.}}<br />
<br />
=== Disabling IPv6 does not work ===<br />
<br />
One option is to add:<br />
<br />
# Disable ipv6<br />
net.ipv6.conf.all.disable_ipv6 = 1<br />
<br />
in a file with a {{ic|.conf}} extension under {{ic|/etc/openrc/sysctl.d}}<br />
<br />
=== During shutdown remounting root as read-only fails ===<br />
<br />
If the above happens, edit the {{ic|/etc/openrc/init.d/mount-ro}} file and put:<br />
<br />
telinit u<br />
<br />
after the following line:<br />
<br />
# Flush all pending disk writes now<br />
sync; sync<br />
<br />
=== /etc/sysctl.conf not found ===<br />
<br />
By default, {{ic|sysctl --system}} is called to load the sysctl configuration. [https://github.com/OpenRC/openrc/blob/master/init.d/sysctl.Linux.in#L17] This includes the {{ic|/etc/sysctl.conf}} file, which was removed from Arch. [https://www.archlinux.org/news/deprecation-of-etcsysctlconf/]<br />
<br />
To prevent a missing file error, create the file:<br />
<br />
# touch /etc/sysctl.conf<br />
<br />
=== X server does not start unless user is root ===<br />
<br />
<br />
With Xorg 1.16, X was made rootless and now relies on systemd-login.<br />
Using {{ic|startx}} will not work as-is when running OpenRC as your init system.<br />
<br />
To solve this, create the {{ic|/etc/X11/Xwrapper.config}} file with the following contents:<br />
<br />
# Xorg.wrapper configuration file<br />
needs_root_rights = yes<br />
<br />
<br />
=== Not authorized to perform operation when mounting device ===<br />
<br />
When you use {{ic|startx}} to start {{ic|Xfce}}, you may not be able mount other devices directly in {{ic|thunar}}, in this case, you can change your {{ic|~/.xinitrc}} file with codes below. [https://bbs.archlinux.org/viewtopic.php?pid=976373#p976373]<br />
<br />
#if [ -d /etc/X11/xinit/xinitrc.d ] ; then<br />
# for f in /etc/X11/xinit/xinitrc.d/?*.sh ; do<br />
# [ -x "$f" ] && . "$f"<br />
# done<br />
# unset f<br />
#fi<br />
exec ck-launch-session startxfce4<br />
<br />
== Using OpenRC with a desktop environment ==<br />
<br />
If using ''OpenRC'' with a [[desktop environment]], ConsoleKit may help. Install the [https://gist.github.com/ad73f9087f39d7cadd8e service] to {{ic|/etc/openrc/init.d}}, and enable it:<br />
<br />
# rc-update add consolekit default<br />
<br />
See [[ConsoleKit]] for more information.<br />
<br />
== See also ==<br />
<br />
* [[Wikipedia:OpenRC]]<br />
* [https://wiki.gentoo.org/wiki/OpenRC Gentoo wiki]<br />
* [https://bbs.archlinux.org/viewtopic.php?id=152606 Forum thread about OpenRC in Arch]<br />
* [http://blog.notfoss.com/posts/openrc-on-arch-linux/ Blog: OpenRC on Arch Linux]<br />
* [https://wiki.manjaro.org/index.php?title=OpenRC,_an_alternative_to_systemd Manjaro wiki]</div>Stbinanhttps://wiki.archlinux.org/index.php?title=OpenRC&diff=468750OpenRC2017-02-21T13:00:40Z<p>Stbinan: /* Troubleshooting */ Add a case from my experience</p>
<hr />
<div>[[Category:Boot process]]<br />
[[ja:OpenRC]]<br />
[[ru:OpenRC]]<br />
{{Related articles start}}<br />
{{Related|eudev}}<br />
{{Related|init}}<br />
{{Related|init Rosetta}}<br />
{{Related|SysVinit}}<br />
{{Related articles end}}<br />
{{Warning|Arch Linux only has official support for [[systemd]]. When using OpenRC, please mention so in support requests.}}<br />
<br />
[https://wiki.gentoo.org/wiki/OpenRC OpenRC] is a service manager maintained by the Gentoo developers. OpenRC is dependency based and works with the system provided init program, normally [[SysVinit]].<br />
<br />
== Installation ==<br />
<br />
OpenRC and accompanying packages are available in the [[AUR]]. For details on init components, see [[Init]].<br />
<br />
Install either the {{AUR|openrc}} or {{AUR|openrc-git}} package. {{AUR|openrc-sysvinit}} or {{Pkg|busybox}} are used as the init process. Service files are available from the {{AUR|openrc-arch-services-git}} package.<br />
<br />
{{Accuracy|{{AUR|openrc-sysvinit}} removes {{Pkg|systemd-sysvcompat}}}}<br />
<br />
To maintain compability with {{AUR|initscripts-fork}}, configuration files are installed to {{ic|'''/etc/openrc/'''}}. The sysvinit init binary is installed to {{ic|/usr/bin/init-openrc}} for compability with {{Pkg|systemd-sysvcompat}} or similar packages.<br />
<br />
=== Booting ===<br />
<br />
For booting with OpenRC add {{Ic|1=init=/usr/bin/init-openrc}} to the [[kernel parameters]]. To switch back to systemd, remove the parameter again.<br />
<br />
The {{Ic|1=/etc/openrc/conf.d}} directory, and the {{Ic|1=/etc/openrc/rc.d}} file is used for configuration.<br />
<br />
== Configuration ==<br />
<br />
For general information on configuring OpenRC, see:<br />
<br />
* [http://www.calculate-linux.org/main/en/openrc_manuals OpenRC manuals]<br />
* [http://www.gentoo.org/doc/en/openrc-migration.xml OpenRC migration]<br />
* [http://wiki.gentoo.org/wiki/OpenRC gentoo wiki]. <br />
<br />
=== Preparation ===<br />
<br />
See [[Init#Configuration]].<br />
<br />
=== Services ===<br />
<br />
OpenRC services are enabled by issuing {{ic|rc-update add ''service_name'' ''runlevel''}} as root. It is recommended to at least enable the following services:<br />
{| class="wikitable"<br />
! Service name<br />
! [https://wiki.gentoo.org/wiki/OpenRC#Named_runlevels Runlevel]<br />
! Description<br />
|-<br />
| udev<br />
| sysinit<br />
| Device hot-plugging<br />
|-<br />
| alsa<br />
| default<br />
| [[ALSA]] state<br />
|-<br />
| acpid<br />
| default<br />
| ACPI events<br />
|-<br />
| dbus<br />
| default<br />
| Messaging bus<br />
|-<br />
| dcron<br />
| default<br />
| Scheduling<br />
|-<br />
| syslog-ng<br />
| default<br />
| System logs<br />
|}<br />
<br />
See also [https://wiki.gentoo.org/wiki/Systemd#Native_services Native services] and [[Daemons]].<br />
<br />
=== Network ===<br />
<br />
The network is configured through {{ic|newnet}}. [https://github.com/funtoo/openrc/blob/master/README.newnet] Modify the {{ic|/etc/openrc/conf.d/network}} file; both the {{ic|ip}} ({{Pkg|iproute2}}) and the {{ic|ifconfig}} ({{Pkg|net-tools}}) commands are supported. Below is an example configuration using {{ic|ip}}.<br />
<br />
{{bc|<br />
<nowiki>ip_eth0="192.168.1.2/24"<br />
defaultiproute="via 192.168.1.1"<br />
ifup_eth0="ip link set \$int mtu 1500"<br />
</nowiki>}}<br />
<br />
The network service is added to the boot runlevel by default, so no further action is required. See [[Network configuration]] for general networking information.<br />
<br />
{{Note|1=You may also use [[NetworkManager]], [[dhcpcd]] or {{AUR|netcfg}} by enabling the respective services. ''netcfg'' mimics the [[netctl]] behaviour (see [https://bbs.archlinux.org/viewtopic.php?pid=1489283#p1489283] if you want to enable profiles connection on booting - requires {{ic|wpa_actiond}}). You could consult the [https://www.archlinux.org/netcfg/features.html official documentation] or [https://wiki.archlinux.org/index.php?title=Netcfg&oldid=243178 old wiki documentation] (be aware of consulting version later than [https://www.archlinux.org/news/netcfg-282-release/ 2012-05-13])}}<br />
<br />
=== Boot logs ===<br />
<br />
To enable boot logging, uncomment the {{ic|1=rc_logger="YES"}} line in {{ic|/etc/openrc/rc.conf}}. When enabled, boot logs are stored in {{ic|/var/log/rc.log}}.<br />
<br />
=== Hostname ===<br />
<br />
OpenRC sets the hostname from {{ic|/etc/openrc/conf.d/hostname}}. The file looks as follows:<br />
<br />
{{bc|# Set to the hostname of this machine<br />
hostname<nowiki>=</nowiki>"myhostname"}}<br />
<br />
=== Kernel modules ===<br />
<br />
OpenRC uses {{ic|/etc/openrc/conf.d/modules}} instead of {{ic|/etc/modules-load.d}}. For example:<br />
<br />
{{hc|/etc/openrc/conf.d/modules|2=<br />
# You should consult your kernel documentation and configuration<br />
# for a list of modules and their options.<br />
<br />
modules="vboxdrv acpi_cpufreq"<br />
}}<br />
<br />
=== Locale ===<br />
<br />
Keyboard layout can be configured via {{ic|/etc/openrc/conf.d/keymaps}} and {{ic|/etc/openrc/conf.d/consolefont}}. You can also configure the settings through the {{ic|/etc/locale.conf}} file, which is sourced via {{ic|/etc/profile.d/locale.sh}}. <br />
<br />
See [http://wiki.gentoo.org/wiki/Localization/HOWTO#Keyboard_layout_for_the_console] and [[Locale]] for details.<br />
<br />
=== DM-Crypt ===<br />
<br />
See [http://gentoo-en.vfose.ru/wiki/DM-Crypt DM-Crypt - Gentoo-en] for automatically mounting encrypted LVM or other block devices.<br />
<br />
== Troubleshooting ==<br />
<br />
=== Error while unmounting /tmp ===<br />
<br />
When shutting the system down, you might get an error message such as <br />
<br />
{{bc|* Unmounting /tmp ... <br />
* in use but fuser finds nothing [ !! ]}}<br />
<br />
This can be fixed by adding<br />
<br />
no_umounts="/tmp"<br />
<br />
to {{ic|/etc/openrc/conf.d/localmount}}<br />
<br />
{{Note|This problem occurs only if your tmp is mounted as a tmpfs.}}<br />
<br />
=== Disabling IPv6 does not work ===<br />
<br />
One option is to add:<br />
<br />
# Disable ipv6<br />
net.ipv6.conf.all.disable_ipv6 = 1<br />
<br />
in a file with a {{ic|.conf}} extension under {{ic|/etc/openrc/sysctl.d}}<br />
<br />
=== During shutdown remounting root as read-only fails ===<br />
<br />
If the above happens, edit the {{ic|/etc/openrc/init.d/mount-ro}} file and put:<br />
<br />
telinit u<br />
<br />
after the following line:<br />
<br />
# Flush all pending disk writes now<br />
sync; sync<br />
<br />
=== /etc/sysctl.conf not found ===<br />
<br />
By default, {{ic|sysctl --system}} is called to load the sysctl configuration. [https://github.com/OpenRC/openrc/blob/master/init.d/sysctl.Linux.in#L17] This includes the {{ic|/etc/sysctl.conf}} file, which was removed from Arch. [https://www.archlinux.org/news/deprecation-of-etcsysctlconf/]<br />
<br />
To prevent a missing file error, create the file:<br />
<br />
# touch /etc/sysctl.conf<br />
<br />
=== X server does not start unless user is root ===<br />
<br />
<br />
With the Xorg release 1.16, X was made rootless by relying on systemd-login.<br />
Using {{ic|startx}} will not work when running OpenRC as init system.<br />
<br />
This can be solved by creating the {{ic|/etc/X11/Xwrapper.config}} file with the contents:<br />
<br />
# Xorg.wraper configuration file<br />
needs_root_rights = yes<br />
<br />
<br />
=== Not authorized to perform operation when mounting device ===<br />
<br />
When you use {{ic|startx}} to start {{ic|Xfce}}, you may not be able mount other devices directly in {{ic|thunar}}, in this case, you can change your {{ic|~/.xinitrc}} file with codes below. [https://bbs.archlinux.org/viewtopic.php?pid=976373#p976373]<br />
<br />
#if [ -d /etc/X11/xinit/xinitrc.d ] ; then<br />
# for f in /etc/X11/xinit/xinitrc.d/?*.sh ; do<br />
# [ -x "$f" ] && . "$f"<br />
# done<br />
# unset f<br />
#fi<br />
exec ck-launch-session startxfce4<br />
<br />
== Using OpenRC with a desktop environment ==<br />
<br />
If using ''OpenRC'' with a [[desktop environment]], ConsoleKit may help. Install the [https://gist.github.com/ad73f9087f39d7cadd8e service] to {{ic|/etc/openrc/init.d}}, and enable it:<br />
<br />
# rc-update add consolekit default<br />
<br />
See [[ConsoleKit]] for more information.<br />
<br />
== See also ==<br />
<br />
* [[Wikipedia:OpenRC]]<br />
* [https://wiki.gentoo.org/wiki/OpenRC Gentoo wiki]<br />
* [https://bbs.archlinux.org/viewtopic.php?id=152606 Forum thread about OpenRC in Arch]<br />
* [http://blog.notfoss.com/posts/openrc-on-arch-linux/ Blog: OpenRC on Arch Linux]<br />
* [https://wiki.manjaro.org/index.php?title=OpenRC,_an_alternative_to_systemd Manjaro wiki]</div>Stbinanhttps://wiki.archlinux.org/index.php?title=GRUB&diff=416386GRUB2016-01-20T18:22:09Z<p>Stbinan: /* GNU/Linux menu entry */ Fix some mistakes</p>
<hr />
<div>[[Category:Boot loaders]]<br />
[[ar:GRUB]]<br />
[[cs:GRUB]]<br />
[[de:GRUB]]<br />
[[el:GRUB]]<br />
[[es:GRUB]]<br />
[[fr:GRUB]]<br />
[[he:GRUB]]<br />
[[id:GRUB]]<br />
[[it:GRUB]]<br />
[[ja:GRUB]]<br />
[[nl:GRUB]]<br />
[[pt:GRUB]]<br />
[[ru:GRUB]]<br />
[[tr:GRUB2]]<br />
[[uk:GRUB]]<br />
[[zh-cn:GRUB]]<br />
[[zh-tw:GRUB]]<br />
{{Related articles start}}<br />
{{Related|Arch boot process}}<br />
{{Related|Boot loaders}}<br />
{{Related|Master Boot Record}}<br />
{{Related|GUID Partition Table}}<br />
{{Related|Unified Extensible Firmware Interface}}<br />
{{Related|GRUB Legacy}}<br />
{{Related|GRUB/EFI examples}}<br />
{{Related|GRUB/Tips and tricks}}<br />
{{Related articles end}}<br />
[https://www.gnu.org/software/grub/ GRUB] — not to be confused with [[GRUB Legacy]] — is the next generation of the GRand Unified Bootloader. GRUB is derived from [http://www.nongnu.org/pupa/ PUPA] which was a research project to develop the next generation of what is now GRUB Legacy. GRUB has been rewritten from scratch to clean up everything and provide modularity and portability [https://www.gnu.org/software/grub/grub-faq.html#q1].<br />
<br />
== Preface ==<br />
<br />
* A ''bootloader'' is the first software program that runs when a computer starts. It is responsible for loading and transferring control to the Linux kernel. The kernel, in turn, initializes the rest of the operating system.<br />
* The name ''GRUB'' officially refers to version ''2'' of the software, see [https://www.gnu.org/software/grub/]. If you are looking for the article on the legacy version, see [[GRUB Legacy]].<br />
* GRUB supports [[Btrfs]] as root (without a separate {{ic|/boot}} file system) compressed with either zlib or LZO<br />
** GRUB currently (Sep 2015) supports booting from [[Btrfs]] RAID 0/1/10, but ''not'' RAID 5/6. You may use [[mdadm]] for RAID 5/6, which is supported by GRUB.<br />
* GRUB does not support [[F2FS]] as root so you will need a separate {{ic|/boot}} with a supported file system.<br />
<br />
== BIOS systems ==<br />
<br />
=== GUID Partition Table (GPT) specific instructions ===<br />
<br />
On a BIOS/[[GPT]] configuration a [http://www.gnu.org/software/grub/manual/html_node/BIOS-installation.html BIOS boot partition] is required. GRUB embeds its {{ic|core.img}} into this partition.<br />
<br />
{{Note|<br />
* Before attempting this method keep in mind that not all systems will be able to support this partitioning scheme, read more on [[GUID Partition Table#BIOS systems|GUID partition tables]].<br />
* This additional partition is only needed on a GRUB, BIOS/GPT partitioning scheme. Previously, for a GRUB, BIOS/MBR partitioning scheme, GRUB used the Post-MBR gap for the embedding the {{ic|core.img}}). GRUB for GPT, however, does not use the Post-GPT gap to conform to GPT specifications that require 1_megabyte/2048_sector disk boundaries.<br />
* For [[UEFI]] systems this extra partition is not required as no embedding of boot sectors takes place in that case.<br />
}}<br />
<br />
Create a mebibyte partition ({{ic|1=+1M}} with {{ic|fdisk}} or {{ic|gdisk}}) on the disk with no file system and type BIOS boot (''BIOS boot'' in fdisk, {{ic|ef02}} in gdisk, {{ic|bios_grub}} in {{ic|parted}}). This partition can be in any position order but has to be on the first 2 TiB of the disk. This partition needs to be created before GRUB installation. When the partition is ready, install the bootloader as per the instructions below.<br />
<br />
The post-GPT gap can also be used as the BIOS boot partition though it will be out of GPT alignment specification. Since the partition will not be regularly accessed performance issues can be disregarded (though some disk utilities will display a warning about it). In {{ic|fdisk}} or {{ic|gdisk}} create a new partition starting at sector 34 and spanning to 2047 and set the type. To have the viewable partitions begin at the base consider adding this partition last.<br />
<br />
=== Master Boot Record (MBR) specific instructions ===<br />
<br />
Usually the post-[[MBR]] gap (after the 512 byte MBR region and before the start of the first partition) in many MBR (or 'msdos' disklabel) partitioned systems is 31 KiB when DOS compatibility cylinder alignment issues are satisfied in the partition table. However a post-MBR gap of about 1 to 2 MiB is recommended to provide sufficient room for embedding GRUB's {{ic|core.img}} ({{bug|24103}}). It is advisable to use a partitioning tool that supports 1 MiB partition alignment to obtain this space as well as to satisfy other non-512 byte sector issues (which are unrelated to embedding of {{ic|core.img}}).<br />
<br />
=== Installation ===<br />
<br />
[[Install]] the {{Pkg|grub}} package. It will replace {{AUR|grub-legacy}}, where already installed.<br />
<br />
{{Note|Simply installing the package will not update the {{ic|/boot/grub/i386-pc/core.img}} file and the GRUB modules in {{ic|/boot/grub/i386-pc}}. You need to update them manually using {{ic|grub-install}} as explained below.}}<br />
<br />
==== Install boot files ====<br />
<br />
There are 4 ways to install GRUB boot files in BIOS booting:<br />
<br />
* [[#Install to disk|Install to disk]] (recommended)<br />
* [[#Install to external USB stick|Install to external USB stick]] (for recovery)<br />
* [[#Install to partition or partitionless disk|Install to partition or partitionless disk]] (not recommended)<br />
* [[#Generate core.img alone|Generate core.img alone]] (safest method, but requires another BIOS bootloader like [[Syslinux]] to be installed to chainload {{ic|/boot/grub/i386-pc/core.img}})<br />
<br />
{{Note|See https://www.gnu.org/software/grub/manual/html_node/BIOS-installation.html for additional documentation.}}<br />
<br />
===== Install to disk =====<br />
<br />
{{Note|The method is specific to installing GRUB to a partitioned (MBR or GPT) disk, with GRUB files installed to {{ic|/boot/grub}} and its first stage code installed to the 440-byte MBR boot code region (not to be confused with MBR partition table). }}<br />
<br />
The following commands will:<br />
* Set up GRUB in the 440-byte Master Boot Record boot code region<br />
* Populate the {{ic|/boot/grub}} directory<br />
* Generate the {{ic|/boot/grub/i386-pc/core.img}} file<br />
* Embed it in the 31 KiB (minimum size - varies depending on partition alignment) post-MBR gap in case of MBR partitioned disk<br />
* In the case of a GPT partitioned disk it will embed it in the BIOS Boot Partition , denoted by {{ic|bios_grub}} flag in parted and EF02 type code in gdisk<br />
<br />
# grub-install --recheck --target=i386-pc /dev/sd''x''<br />
# grub-mkconfig -o /boot/grub/grub.cfg<br />
<br />
If you use [[LVM]] for your {{ic|/boot}}, you can install GRUB on multiple physical disks.<br />
<br />
===== Install to external USB stick =====<br />
<br />
Assume your USB stick's first partition is FAT32 and its partition is /dev/sdy1<br />
<br />
# mkdir -p /mnt/usb ; mount /dev/sdy1 /mnt/usb<br />
# grub-install --target=i386-pc --recheck --debug --boot-directory=/mnt/usb/boot /dev/sdy<br />
# grub-mkconfig -o /mnt/usb/boot/grub/grub.cfg<br />
<br />
# optional, backup config files of grub.cfg<br />
# mkdir -p /mnt/usb/etc/default<br />
# cp /etc/default/grub /mnt/usb/etc/default<br />
# cp -a /etc/grub.d /mnt/usb/etc<br />
<br />
# sync; umount /mnt/usb<br />
<br />
===== Install to partition or partitionless disk =====<br />
{{Warning|GRUB '''strongly discourages''' installation to a partition boot sector or a partitionless disk as GRUB Legacy or Syslinux does. This setup is prone to breakage, especially during updates, and is '''not supported''' by the Arch developers.}}<br />
<br />
To set up grub to a partition boot sector, to a partitionless disk (also called superfloppy) or to a floppy disk, run (using for example {{ic|/dev/sdaX}} as the {{ic|/boot}} partition):<br />
<br />
# chattr -i /boot/grub/i386-pc/core.img<br />
# grub-install --target=i386-pc --recheck --debug --force /dev/sdaX<br />
# chattr +i /boot/grub/i386-pc/core.img<br />
<br />
{{Note|<br />
* {{ic|/dev/sdaX}} used for example only.<br />
* {{ic|1=--target=i386-pc}} instructs {{ic|grub-install}} to install for BIOS systems only. It is recommended to always use this option to remove ambiguity in ''grub-install''.<br />
}}<br />
<br />
You need to use the {{ic|--force}} option to allow usage of blocklists and should not use {{ic|1=--grub-setup=/bin/true}} (which is similar to simply generating {{ic|core.img}}).<br />
<br />
{{ic|grub-install}} will give out warnings like which should give you the idea of what might go wrong with this approach:<br />
<br />
/sbin/grub-setup: warn: Attempting to install GRUB to a partitionless disk or to a partition. This is a BAD idea.<br />
/sbin/grub-setup: warn: Embedding is not possible. GRUB can only be installed in this setup by using blocklists.<br />
However, blocklists are UNRELIABLE and their use is discouraged.<br />
<br />
Without {{ic|--force}} you may get the below error and {{ic|grub-setup}} will not setup its boot code in the partition boot sector:<br />
<br />
/sbin/grub-setup: error: will not proceed with blocklists<br />
<br />
With {{ic|--force}} you should get:<br />
<br />
Installation finished. No error reported.<br />
<br />
The reason why {{ic|grub-setup}} does not by default allow this is because in case of partition or a partitionless disk is that GRUB relies on embedded blocklists in the partition bootsector to locate the {{ic|/boot/grub/i386-pc/core.img}} file and the prefix directory {{ic|/boot/grub}}. The sector locations of {{ic|core.img}} may change whenever the file system in the partition is being altered (files copied, deleted etc.). For more info, see https://bugzilla.redhat.com/show_bug.cgi?id=728742 and https://bugzilla.redhat.com/show_bug.cgi?id=730915.<br />
<br />
The workaround for this is to set the immutable flag on {{ic|/boot/grub/i386-pc/core.img}} (using {{ic|chattr}} command as mentioned above) so that the sector locations of the {{ic|core.img}} file in the disk is not altered. The immutable flag on {{ic|/boot/grub/i386-pc/core.img}} needs to be set only if GRUB is installed to a partition boot sector or a partitionless disk, not in case of installation to MBR or simple generation of {{ic|core.img}} without embedding any bootsector (mentioned above).<br />
<br />
Unfortunately, the {{ic|grub.cfg}} file that is created will not contain the proper UUID in order to boot, even if it reports no errors. see https://bbs.archlinux.org/viewtopic.php?pid=1294604#p1294604.<br />
In order to fix this issue the following commands:<br />
<br />
# mount /dev/sdxY /mnt #Your root partition.<br />
# mount /dev/sdxZ /mnt/boot #Your boot partition (if you have one).<br />
# arch-chroot /mnt<br />
# pacman -S linux<br />
# grub-mkconfig -o /boot/grub/grub.cfg<br />
<br />
===== Generate core.img alone =====<br />
<br />
To populate the {{ic|/boot/grub}} directory and generate a {{ic|/boot/grub/i386-pc/core.img}} file '''without''' embedding any GRUB bootsector code in the MBR, post-MBR region, or the partition bootsector, add {{ic|1=--grub-setup=/bin/true}} to {{ic|grub-install}}:<br />
<br />
# grub-install --target=i386-pc --grub-setup=/bin/true --recheck --debug /dev/sda<br />
<br />
{{Note|<br />
* {{ic|/dev/sda}} used for example only.<br />
* {{ic|1=--target=i386-pc}} instructs {{ic|grub-install}} to install for BIOS systems only. It is recommended to always use this option to remove ambiguity in grub-install.<br />
}}<br />
<br />
You can then chainload GRUB's {{ic|core.img}} from GRUB Legacy or syslinux as a Linux kernel or as a multiboot kernel (see also [[Syslinux#Chainloading]]).<br />
<br />
== UEFI systems ==<br />
<br />
{{Note|<br />
* It is recommended to read and understand the [[UEFI]], [[GPT]] and [[UEFI Bootloaders]] pages.<br />
* When installing to use UEFI it is important to start the install with your machine in UEFI mode. The Arch Linux install media must be UEFI bootable.<br />
}}<br />
<br />
=== Check if you have GPT and an ESP ===<br />
<br />
An EFI System Partition (ESP) is needed on every disc you want to boot using EFI. GPT is not strictly necessary, but it is highly recommended and is the only method currently supported in this article. If you are installing Arch Linux on an EFI-capable computer with an already-working operating system, like Windows 8 for example, it is very likely that you already have an ESP. To check for GPT and for an ESP, use {{ic|parted}} as root to print the partition table of the disk you want to boot from. (We are calling it {{ic|/dev/sda}}.)<br />
<br />
# parted /dev/sda print<br />
<br />
For GPT, you are looking for "Partition Table: GPT". For EFI, you are looking for a small (512 MiB or less) partition with a vfat file system and the ''boot'' flag enabled. On it, there should be a directory named "EFI". If these criteria are met, this is your ESP. Make note of the partition number. You will need to know which one it is, so you can mount it later on while installing GRUB to it.<br />
<br />
=== Create an ESP ===<br />
<br />
If you do not have an ESP, you will need to create one. See [[UEFI#EFI System Partition]]<br />
<br />
=== Installation ===<br />
<br />
{{Note|UEFI firmware are not implemented consistently by hardware manufacturers. The installation examples provided are intended to work on the widest range of UEFI systems possible. Those experiencing problems despite applying these methods are encouraged to share detailed information for their hardware-specific cases, especially where solving these problems. A [[GRUB/EFI examples]] article has been provided for such cases.}}<br />
<br />
This section assumes you are installing GRUB for x86_64 systems (x86_64-efi). For i686 systems, replace {{ic|x86_64-efi}} with {{ic|i386-efi}} where appropriate.<br />
<br />
Make sure you are in a [[bash]] shell. For example, when booting from the Arch ISO:<br />
<br />
# arch-chroot /mnt /bin/bash<br />
<br />
[[Install]] the packages {{Pkg|grub}} and {{Pkg|efibootmgr}}. ''GRUB'' is the bootloader, ''efibootmgr'' creates bootable {{ic|.efi}} stub entries used by the GRUB installation script.<br />
<br />
The following steps install the GRUB UEFI application to {{ic|'''$esp'''/EFI/grub}}, install its modules to {{ic|/boot/grub/x86_64-efi}}, and place the bootable {{ic|grubx64.efi}} stub in {{ic|'''$esp'''/EFI/grub}}.<br />
<br />
First, tell GRUB to use UEFI, set the boot directory and set the bootloader ID. Change {{ic|$esp}} to your efi partition (usually {{ic|/boot}}):<br />
<br />
# grub-install --target=x86_64-efi --efi-directory='''$esp''' --bootloader-id='''grub''' --recheck<br />
<br />
The {{ic|--bootloader-id}} is what appears in the boot options to identity the GRUB EFI boot option; make sure this is something you will recognize later. The install will create a directory of the same name under {{ic|$esp/EFI/}} where the EFI binary bootloader will be placed. <br />
<br />
After the above install finished the main GRUB directory is located at {{ic|/boot/grub/}}. <br />
<br />
Remember to [[#Generate the main configuration file]] after finalizing further setup dependant [[#Configuration]]. <br />
<br />
{{Note|<br />
* While some distributions require a {{ic|/boot/efi}} or {{ic|/boot/EFI}} directory, Arch does not.<br />
* {{ic|--efi-directory}} and {{ic|--bootloader-id}} are specific to GRUB UEFI. {{ic|--efi-directory}} specifies the mountpoint of the ESP. It replaces {{ic|--root-directory}}, which is deprecated. <br />
* You might note the absence of a <device_path> option (e.g.: {{ic|/dev/sda}}) in the {{ic|grub-install}} command. In fact any <device_path> provided will be ignored by the GRUB install script, as UEFI bootloaders do not use a MBR or partition boot sector at all.<br />
}}<br />
<br />
See [[#UEFI|UEFI troubleshooting]] in case of problems.<br />
<br />
=== Further reading ===<br />
<br />
Below is other relevant information regarding installing Arch via UEFI<br />
<br />
==== Alternative install method ====<br />
<br />
Usually, GRUB keeps all files, including configuration files, in {{ic|/boot}}, regardless of where the EFI System Partition is mounted.<br />
<br />
If you want to keep these files inside the EFI System Partition itself, add {{ic|--boot-directory&#61;$esp}} to the grub-install command:<br />
<br />
# grub-install --target=x86_64-efi --efi-directory=$esp --bootloader-id=grub --boot-directory=$esp --recheck --debug<br />
<br />
This puts all GRUB files in {{ic|$esp/grub}}, instead of in {{ic|/boot/grub}}. When using this method, make sure you have ''grub-mkconfig'' put the configuration file in the same place:<br />
<br />
# grub-mkconfig -o $esp/grub/grub.cfg<br />
<br />
Configuration is otherwise the same.<br />
<br />
==== UEFI firmware workaround ====<br />
<br />
Some UEFI firmware requires that the bootable {{ic|.efi}} stub have a specific name and be placed in a specific location: {{ic|$esp/EFI/boot/bootx64.efi}} (where {{ic|$esp}} is the UEFI partition mountpoint). Failure to do so in such instances will result in an unbootable installation. Fortunately, this will not cause any problems with other firmware that does not require this.<br />
<br />
To do so, first create the necessary directory, and then copy across the grub {{ic|.efi}} stub, renaming it in the process:<br />
<br />
# mkdir $esp/EFI/boot<br />
# cp $esp/EFI/grub_uefi/grubx64.efi $esp/EFI/boot/bootx64.efi<br />
<br />
==== Create a GRUB entry in the firmware boot manager ====<br />
{{ic|grub-install}} automatically tries to create a menu entry in the boot manager. If it does not, then see [[UEFI#efibootmgr]] for instructions to use {{ic|efibootmgr}} to create a menu entry. However, the problem is likely to be that you have not booted your CD/USB in UEFI mode, as in [[UEFI#Create UEFI bootable USB from ISO]].<br />
<br />
==== GRUB standalone ====<br />
<br />
This section assumes you are creating a standalone GRUB for x86_64 systems (x86_64-efi). For i686 systems, replace {{ic|x86_64-efi}} with {{ic|i386-efi}} where appropriate.<br />
<br />
It is possible to create a {{ic|grubx64_standalone.efi}} application which has all the modules embedded in a tar archive within the UEFI application, thus removing the need for having a separate directory populated with all of the GRUB UEFI modules and other related files. This is done using the {{ic|grub-mkstandalone}} command (included in {{Pkg|grub}}) as follows:<br />
<br />
# echo 'configfile ${cmdpath}/grub.cfg' > /tmp/grub.cfg<br />
# grub-mkstandalone -d /usr/lib/grub/x86_64-efi/ -O x86_64-efi --modules="part_gpt part_msdos" --fonts="unicode" --locales="en@quot" --themes="" -o "$esp/EFI/grub/grubx64_standalone.efi" "boot/grub/grub.cfg=/tmp/grub.cfg" -v<br />
<br />
Then copy the GRUB config file to {{ic|$esp/EFI/grub/grub.cfg}} and create a UEFI Boot Manager entry for {{ic|$esp/EFI/grub/grubx64_standalone.efi}} using [[UEFI#efibootmgr|efibootmgr]].<br />
<br />
{{Note|<br />
The option {{ic|1=--modules="part_gpt part_msdos"}} (with the quotes) is necessary for the {{ic|${cmdpath} }} feature to work properly.<br />
}}<br />
<br />
{{Warning|You may find that the {{ic|grub.cfg}} file is not loaded due to {{ic|${cmdpath} }} missing a slash (i.e. {{ic|(hd1,msdos2)EFI/Boot}} instead of {{ic|(hd1,msdos2)/EFI/Boot}}) and so you are dropped into a GRUB shell. If this happens determine what {{ic|${cmdpath} }} is set to ({{ic|echo ${cmdpath} }}) and then load the config file manually (e.g. {{ic|configfile (hd1,msdos2)/EFI/Boot/grub.cfg}}).}}<br />
<br />
==== Technical information ====<br />
<br />
The GRUB EFI file always expects its config file to be at {{ic|${prefix}/grub.cfg}}. However in the standalone GRUB EFI file, the {{ic|${prefix} }} is located inside a tar archive and embedded inside the standalone GRUB EFI file itself (inside the GRUB environment, it is denoted by {{ic|"(memdisk)"}}, without quotes). This tar archive contains all the files that would be stored normally at {{ic|/boot/grub}} in case of a normal GRUB EFI install.<br />
<br />
Due to this embedding of {{ic|/boot/grub}} contents inside the standalone image itself, it does not rely on actual (external) {{ic|/boot/grub}} for anything. Thus in case of standalone GRUB EFI file {{ic|1=${prefix}==(memdisk)/boot/grub}} and the standalone GRUB EFI file reads expects the config file to be at {{ic|1=${prefix}/grub.cfg==(memdisk)/boot/grub/grub.cfg}}.<br />
<br />
Hence to make sure the standalone GRUB EFI file reads the external {{ic|grub.cfg}} located in the same directory as the EFI file (inside the GRUB environment, it is denoted by {{ic|${cmdpath} }}), we create a simple {{ic|/tmp/grub.cfg}} which instructs GRUB to use {{ic|${cmdpath}/grub.cfg}} as its config ({{ic|configfile ${cmdpath}/grub.cfg}} command in {{ic|(memdisk)/boot/grub/grub.cfg}}). We then instruct grub-mkstandalone to copy this {{ic|/tmp/grub.cfg}} file to {{ic|${prefix}/grub.cfg}} (which is actually {{ic|(memdisk)/boot/grub/grub.cfg}}) using the option {{ic|1="boot/grub/grub.cfg=/tmp/grub.cfg"}}.<br />
<br />
This way, the standalone GRUB EFI file and actual {{ic|grub.cfg}} can be stored in any directory inside the EFI System Partition (as long as they are in the same directory), thus making them portable.<br />
<br />
== Generate the main configuration file ==<br />
<br />
After the installation, the main configuration file {{ic|grub.cfg}} needs to be generated. The generation process can be influenced by a variety of options in {{ic|/etc/default/grub}} and scripts in {{ic|/etc/grub.d/}}; see [[#Configuration]]. <br />
<br />
If you have not done additional configuration, the automatic generation will determine the root filesystem of the system to boot for the configuration file. For that to succeed it is important that the system is either booted or chrooted into. <br />
<br />
{{Note|Remember that {{ic|grub.cfg}} has to be re-generated after any change to {{ic|/etc/default/grub}} or files in {{ic|/etc/grub.d/}}.}}<br />
<br />
Use the ''grub-mkconfig'' tool to generate {{ic|grub.cfg}}:<br />
<br />
# grub-mkconfig -o /boot/grub/grub.cfg<br />
<br />
{{Note|<br />
* The default file path is {{ic|/boot/grub/grub.cfg}}, not {{ic|/boot/grub/i386-pc/grub.cfg}}. The {{Pkg|grub}} includes a sample {{ic|/boot/grub/grub.cfg}}; ensure your intended changes were written to this file.<br />
* If you are trying to run ''grub-mkconfig'' in a chroot or ''systemd-nspawn'' container, you might notice that it does not work, complaining that ''grub-probe'' cannot get the "canonical path of /dev/sdaX". In this case, try using ''arch-chroot'' as described in the [https://bbs.archlinux.org/viewtopic.php?pid&#61;1225067#p1225067 BBS post].<br />
}}<br />
<br />
By default the generation scripts automatically add menu entries for Arch Linux to any generated configuration. See [[#Dual-booting]] for configuration with other systems.<br />
<br />
== Configuration ==<br />
<br />
This section only covers editing the {{ic|/etc/default/grub}} configuration file. See [[GRUB/Tips and tricks]] for more information.<br />
<br />
Remember to always [[#Generate the main configuration file]] after making changes to {{ic|/etc/default/grub}}.<br />
<br />
=== Additional arguments ===<br />
<br />
To pass custom additional arguments to the Linux image, you can set the {{ic|GRUB_CMDLINE_LINUX}} + {{ic|GRUB_CMDLINE_LINUX_DEFAULT}} variables in {{ic|/etc/default/grub}}. The two are appended to each other and passed to kernel when generating regular boot entries. For the ''recovery'' boot entry, only {{ic|GRUB_CMDLINE_LINUX}} is used in the generation.<br />
<br />
It is not necessary to use both, but can be useful. For example, you could use {{ic|<nowiki>GRUB_CMDLINE_LINUX_DEFAULT="resume=/dev/sdaX</nowiki> quiet"}} where {{ic|sda'''X'''}} is your swap partition to enable resume after hibernation. This would generate a recovery boot entry without the resume and without ''quiet'' suppressing kernel messages during a boot from that menu entry. Though, the other (regular) menu entries would have them as options.<br />
<br />
By default ''grub-mkconfig'' determines the [[UUID]] of the root filesystem for the configuration. To disable this, uncomment {{ic|1=GRUB_DISABLE_LINUX_UUID=true}}. <br />
<br />
For generating the GRUB recovery entry you also have to comment out {{ic|<nowiki>#GRUB_DISABLE_RECOVERY=true</nowiki>}} in {{ic|/etc/default/grub}}.<br />
<br />
You can also use {{ic|<nowiki>GRUB_CMDLINE_LINUX="resume=UUID=uuid-of-swap-partition"</nowiki>}}<br />
<br />
See [[Kernel parameters]] for more info.<br />
<br />
=== Dual-booting ===<br />
<br />
{{Tip|To have ''grub-mkconfig'' search for other installed systems, [[install]] {{Pkg|os-prober}}.}}<br />
<br />
==== Automatically generating using /etc/grub.d/40_custom and grub-mkconfig ====<br />
<br />
The best way to add other entries is editing the {{ic|/etc/grub.d/40_custom}} or {{ic|/boot/grub/custom.cfg}}. The entries in this file will be automatically added when running {{ic|grub-mkconfig}}.<br />
After adding the new lines, run:<br />
{{bc|<nowiki># grub-mkconfig -o /boot/grub/grub.cfg</nowiki>}}<br />
or, for UEFI-GPT Mode (As per [[#Alternative install method]]):<br />
{{bc|<nowiki># grub-mkconfig -o /boot/efi/EFI/GRUB/grub.cfg</nowiki>}}<br />
to generate an updated {{ic|grub.cfg}}.<br />
<br />
For example, a typical {{ic|/etc/grub.d/40_custom}} file, could appear similar to the following one, created for [http://h10025.www1.hp.com/ewfrf/wc/product?cc=us&destPage=product&lc=en&product=5402703&tmp_docname= HP Pavilion 15-e056sl Notebook PC], originally with Microsoft Windows 8 preinstalled. Each {{ic|menuentry}} should maintain a structure similar to the following ones. Note that the UEFI partition {{ic|/dev/sda2}} within GRUB is called {{ic|hd0,gpt2}} and {{ic|ahci0,gpt2}} (see [[#Windows installed in UEFI-GPT Mode menu entry|here]] for more info).<br />
<br />
{{hc|/etc/grub.d/40_custom|<nowiki>#!/bin/sh<br />
exec tail -n +3 $0<br />
# This file provides an easy way to add custom menu entries.&nbsp; Simply type the<br />
# menu entries you want to add after this comment.&nbsp; Be careful not to change<br />
# the 'exec tail' line above.<br />
<br />
menuentry "HP / Microsoft Windows 8.1" {<br />
echo "Loading HP / Microsoft Windows 8.1..."<br />
insmod part_gpt<br />
insmod fat<br />
insmod search_fs_uuid<br />
insmod chain<br />
search --fs-uuid --no-floppy --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 763A-9CB6<br />
chainloader /EFI/Microsoft/Boot/bootmgfw.efi<br />
}<br />
<br />
menuentry "HP / Microsoft Control Center" {<br />
echo "Loading HP / Microsoft Control Center..."<br />
insmod part_gpt<br />
insmod fat<br />
insmod search_fs_uuid<br />
insmod chain<br />
search --fs-uuid --no-floppy --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 763A-9CB6<br />
chainloader /EFI/HP/boot/bootmgfw.efi<br />
}<br />
<br />
menuentry "System shutdown" {<br />
echo "System shutting down..."<br />
halt<br />
}<br />
<br />
menuentry "System restart" {<br />
echo "System rebooting..."<br />
reboot<br />
}</nowiki>}}<br />
<br />
===== GNU/Linux menu entry =====<br />
Assuming that the other distro is on partition {{ic|sda2}}:<br />
<br />
{{bc|<nowiki>menuentry "Other Linux" {<br />
set root=(hd0,2)<br />
linux /boot/vmlinuz (add other options here as required)<br />
initrd /boot/initrd.img (if the other kernel uses/needs one)<br />
}</nowiki>}}<br />
<br />
Alternatively let grub search for the right partition by ''UUID'' or ''label'':<br />
<br />
{{bc|<nowiki>menuentry "Other Linux" {<br />
# assuming that UUID is 763A-9CB6<br />
search --set=root --fs-uuid 763A-9CB6<br />
<br />
# search by label OTHER_LINUX (make sure that partition label is unambiguous)<br />
#search --set=root --label OTHER_LINUX<br />
<br />
linux /boot/vmlinuz (add other options here as required, for example: root=UUID=763A-9CB6)<br />
initrd /boot/initrd.img (if the other kernel uses/needs one)<br />
}</nowiki>}}<br />
<br />
For some os like Nix OS and GuixSD, because the kernel files are named different and are in a special place called store, the entry will be a bit different, below it's an example for GuixSD:<br />
<br />
{{bc|<nowiki>menuentry "GNU with Linux-Libre 4.2.5 (alpha)" {<br />
search --set=root --fs-uuid YOUR_ROOT_PARTITION_UUID<br />
search --file --set /gnu/store/zbm09fk0wxkw2wyygnn4gcfxj8s31ajd-linux-libre-4.2.5/bzImage<br />
<br />
linux /gnu/store/zbm09fk0wxkw2wyygnn4gcfxj8s31ajd-linux-libre-4.2.5/bzImage --root=YOUR_ROOT_PARTITION_LABEL --system=/gnu/store/a1brgzara5mw72jnmhqjx0j69ah8p5mp-system --load=/gnu/store/a1brgzara5mw72jnmhqjx0j69ah8p5mp-system/boot<br />
initrd /gnu/store/a1brgzara5mw72jnmhqjx0j69ah8p5mp-system/initrd<br />
}</nowiki>}}<br />
<br />
===== FreeBSD menu entry =====<br />
The following three methods require that FreeBSD is installed on a single partition with UFS(v2). Assuming the nested BSD partition table is on {{ic|sda4}}:<br />
<br />
====== Loading the kernel directly ======<br />
{{bc|1=<br />
menuentry 'FreeBSD' {<br />
insmod ufs2<br />
set root='hd0,gpt4,bsd1'<br />
## or 'hd0,msdos4,bsd1', if using an IBM-PC (MS-DOS) style partition table<br />
kfreebsd /boot/kernel/kernel<br />
kfreebsd_loadenv /boot/device.hints<br />
set kFreeBSD.vfs.root.mountfrom=ufs:/dev/ada0s4a<br />
set kFreeBSD.vfs.root.mountfrom.options=rw<br />
}<br />
}}<br />
<br />
====== Chainloading the embedded boot record ======<br />
{{bc|1=<br />
menuentry 'FreeBSD' {<br />
insmod ufs2<br />
set root='hd0,gpt4,bsd1'<br />
chainloader +1<br />
}<br />
}}<br />
<br />
====== Running the traditional BSD 2nd stage loader ======<br />
{{bc|1=<br />
menuentry 'FreeBSD' {<br />
insmod ufs2<br />
set root='(hd0,4)'<br />
kfreebsd /boot/loader<br />
}<br />
}}<br />
<br />
===== Windows XP menu entry=====<br />
This assumes that your Windows partition is {{ic|sda3}}. Remember you need to point set root and chainloader to the system reserve partition that windows made when it installed, not the actual partition windows is on. This example works if your system reserve partition is {{ic|sda3}}.<br />
<br />
{{bc|<nowiki># (2) Windows XP<br />
menuentry "Windows XP" {<br />
set root="(hd0,3)"<br />
chainloader +1<br />
}</nowiki>}}<br />
<br />
If the Windows bootloader is on an entirely different hard drive than GRUB, it may be necessary to trick Windows into believing that it is the first hard drive. This was possible with {{ic|drivemap}}. Assuming GRUB is on {{ic|hd0}} and Windows is on {{ic|hd2}}, you need to add the following after {{ic|set root}}:<br />
<br />
{{bc|drivemap -s hd0 hd2}}<br />
<br />
===== Windows installed in UEFI-GPT Mode menu entry =====<br />
<br />
{{Note|This menuentry will work only in UEFI boot mode and only if the Windows bitness matches the UEFI bitness. It '''WILL NOT WORK''' in BIOS installed GRUB. See [[Dual boot with Windows#Windows UEFI vs BIOS limitations]] and [[Dual boot with Windows#Bootloader UEFI vs BIOS limitations]] for more info.}}<br />
<br />
{{bc|<nowiki>if [ "${grub_platform}" == "efi" ]; then<br />
menuentry "Microsoft Windows Vista/7/8/8.1 UEFI-GPT" {<br />
insmod part_gpt<br />
insmod fat<br />
insmod search_fs_uuid<br />
insmod chain<br />
search --fs-uuid --set=root $hints_string $fs_uuid<br />
chainloader /EFI/Microsoft/Boot/bootmgfw.efi<br />
}<br />
fi</nowiki>}}<br />
<br />
where {{ic|$hints_string}} and {{ic|$fs_uuid}} are obtained with the following two commands. {{ic|$fs_uuid}}'s command:<br />
<br />
{{hc|1=# grub-probe --target=fs_uuid $esp/EFI/Microsoft/Boot/bootmgfw.efi|2=<br />
1ce5-7f28<br />
}}<br />
<br />
{{ic|$hints_string}}'s command:<br />
<br />
{{hc|1=# grub-probe --target=hints_string $esp/EFI/Microsoft/Boot/bootmgfw.efi|2=<br />
--hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1<br />
}}<br />
<br />
These two commands assume the ESP Windows uses is mounted at {{ic|$esp}}. There might be case differences in the path to Windows's EFI file, what with being Windows, and all.<br />
<br />
===== "Shutdown" menu entry =====<br />
<br />
{{bc|<nowiki>menuentry "System shutdown" {<br />
echo "System shutting down..."<br />
halt<br />
}</nowiki>}}<br />
<br />
===== "Restart" menu entry =====<br />
<br />
{{bc|<nowiki>menuentry "System restart" {<br />
echo "System rebooting..."<br />
reboot<br />
}</nowiki>}}<br />
<br />
===== Windows installed in BIOS-MBR mode =====<br />
<br />
{{Poor writing|This section does not fit into the others, should be slimmed down a bit.}}<br />
<br />
{{Note|GRUB supports booting {{ic|bootmgr}} directly and chainload of partition boot sector is no longer required to boot Windows in a BIOS-MBR setup.}}<br />
<br />
{{Warning|It is the '''system partition''' that has {{ic|/bootmgr}}, not your "real" Windows partition (usually C:). In {{ic|blkid}} output, the system partition is the one with {{ic|LABEL&#61;"SYSTEM RESERVED"}} or {{ic|LABEL&#61;"SYSTEM"}} and is only about 100 to 200 MB in size (much like the boot partition for Arch). See [[Wikipedia:System partition and boot partition]] for more info.}}<br />
<br />
Throughout this section, it is assumed your Windows partition is {{ic|/dev/sda1}}. A different partition will change every instance of hd0,msdos1. First, find the UUID of the NTFS file system of the Windows's SYSTEM PARTITION where the {{ic|bootmgr}} and its files reside. For example, if Windows {{ic|bootmgr}} exists at {{ic|/media/SYSTEM_RESERVED/bootmgr}}:<br />
<br />
For Windows Vista/7/8/8.1:<br />
<br />
# grub-probe --target=fs_uuid /media/SYSTEM_RESERVED/bootmgr<br />
69B235F6749E84CE<br />
<br />
# grub-probe --target=hints_string /media/SYSTEM_RESERVED/bootmgr<br />
--hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1<br />
<br />
{{Note|For Windows XP, replace {{ic|bootmgr}} with {{ic|NTLDR}} in the above commands. And note that there may not be a separate SYSTEM_RESERVED partition; just probe the file NTLDR on your Windows partition.}}<br />
<br />
Then, add the below code to {{ic|/etc/grub.d/40_custom}} or {{ic|/boot/grub/custom.cfg}} and regenerate {{ic|grub.cfg}} with {{ic|grub-mkconfig}} as explained above to boot Windows (XP, Vista, 7 or 8) installed in BIOS-MBR mode:<br />
<br />
{{Note|These menuentries will work only in Legacy BIOS boot mode. It WILL NOT WORK in uefi installed grub(2). See [[Dual boot with Windows#Windows UEFI vs BIOS limitations]] and [[Dual boot with Windows#Bootloader UEFI vs BIOS limitations]].}}<br />
<br />
For Windows Vista/7/8/8.1:<br />
<br />
if [ "${grub_platform}" == "pc" ]; then<br />
menuentry "Microsoft Windows Vista/7/8/8.1 BIOS-MBR" {<br />
insmod part_msdos<br />
insmod ntfs<br />
insmod search_fs_uuid<br />
insmod ntldr <br />
search --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 69B235F6749E84CE<br />
ntldr /bootmgr<br />
}<br />
fi<br />
<br />
For Windows XP:<br />
<br />
if [ "${grub_platform}" == "pc" ]; then<br />
menuentry "Microsoft Windows XP" {<br />
insmod part_msdos<br />
insmod ntfs<br />
insmod search_fs_uuid<br />
insmod ntldr <br />
search --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 69B235F6749E84CE<br />
ntldr /ntldr<br />
}<br />
fi<br />
<br />
{{Note|In some cases, mine I have installed GRUB before a clean Windows 8, you cannot boot Windows having an error with {{ic|\boot\bcd}} (error code {{ic|0xc000000f}}). You can fix it going to Windows Recovery Console (cmd from install disk) and executing:<br />
x:\> "bootrec.exe /fixboot" <br />
x:\> "bootrec.exe /RebuildBcd".<br />
Do '''not''' use {{ic|bootrec.exe /Fixmbr}} because it will wipe GRUB out.}}<br />
<br />
{{ic|/etc/grub.d/40_custom}} can be used as a template to create {{ic|/etc/grub.d/nn_custom}}. Where {{ic|nn}} defines the precendence, indicating the order the script is executed. The order scripts are executed determine the placement in the grub boot menu.<br />
<br />
{{Note|{{ic|nn}} should be greater than 06 to ensure necessary scripts are executed first.}}<br />
<br />
==== With Windows via EasyBCD and NeoGRUB ====<br />
<br />
{{Merge|NeoGRUB|New page has been created, so this section should be merged there.}}<br />
<br />
Since EasyBCD's NeoGRUB currently does not understand the GRUB menu format, chainload to it by replacing the contents of your {{ic|C:\NST\menu.lst}} file with lines similar to the following:<br />
<br />
default 0<br />
timeout 1<br />
<br />
title Chainload into GRUB v2<br />
root (hd0,7)<br />
kernel /boot/grub/i386-pc/core.img<br />
<br />
Finally, [[#Generate the main configuration file]].<br />
<br />
==== parttool for hide/unhide ====<br />
<br />
If you have a Windows 9x paradigm with hidden {{ic|C:\}} disks GRUB can hide/unhide it using {{ic|parttool}}. For example, to boot the third {{ic|C:\}} disk of three Windows 9x installations on the CLI enter the CLI and:<br />
parttool hd0,1 hidden+ boot-<br />
parttool hd0,2 hidden+ boot-<br />
parttool hd0,3 hidden- boot+<br />
set root=hd0,3<br />
chainloader +1<br />
boot<br />
<br />
=== LVM ===<br />
<br />
If you use [[LVM]] for your {{ic|/boot}}, make sure that the {{ic|lvm}} module is preloaded:<br />
<br />
{{hc|/etc/default/grub|2=<br />
GRUB_PRELOAD_MODULES="lvm"<br />
}}<br />
<br />
=== RAID ===<br />
<br />
GRUB provides convenient handling of RAID volumes. You need to add {{ic|insmod mdraid}} which allows you to address the volume natively. For example, {{ic|/dev/md0}} becomes:<br />
set root=(md/0)<br />
<br />
whereas a partitioned RAID volume (e.g. {{ic|/dev/md0p1}}) becomes:<br />
set root=(md/0,1)<br />
<br />
To install grub when using RAID1 as the {{ic|/boot}} partition (or using {{ic|/boot}} housed on a RAID1 root partition), on devices with GPT ef02/'BIOS boot partition', simply run ''grub-install'' on both of the drives, such as:<br />
# grub-install --target=i386-pc --recheck --debug /dev/sda<br />
# grub-install --target=i386-pc --recheck --debug /dev/sdb<br />
<br />
Where the RAID 1 array housing {{ic|/boot}} is housed on {{ic|/dev/sda}} and {{ic|/dev/sdb}}.<br />
<br />
=== Multiple entries ===<br />
<br />
For tips on managing multiple GRUB entries, for example when using both {{Pkg|linux}} and {{Pkg|linux-lts}} kernels, see [[GRUB/Tips and tricks#Multiple entries]].<br />
<br />
=== Encryption ===<br />
<br />
==== Root partition ====<br />
<br />
For an encrypted root filesystem, it is necessary to edit {{ic|/etc/default/grub}} with the parameters required to unlock the encrypted filesystem during boot. For example, if the [[mkinitcpio]] {{ic|encrypt}} hook is used, the {{ic|cryptdevice}} parameter must be added to {{ic|GRUB_CMDLINE_LINUX<nowiki>=</nowiki>""}} command. In the example below, the {{ic|sda2}} partition has been encrypted as {{ic|/dev/mapper/cryptroot}}:<br />
<br />
{{hc|/etc/default/grub|2=<br />
GRUB_CMDLINE_LINUX="cryptdevice=/dev/sda2:cryptroot"<br />
}}<br />
<br />
Once {{ic|/etc/default/grub}} has been amended, it will then be necessary to [[#Generate the main configuration file]].<br />
<br />
For further information about bootloader configuration for encrypted devices, see [[Dm-crypt/System configuration#Boot loader]].<br />
<br />
{{Tip|If you are upgrading from a working GRUB Legacy configuration, check {{ic|/boot/grub/menu.lst.pacsave}} for the correct device/label to add. Look for them after the text {{ic|kernel /vmlinuz-linux}}.}}<br />
<br />
==== Boot partition ====<br />
<br />
The GRUB [https://www.gnu.org/software/grub/manual/grub.html#Simple-configuration parameter] {{ic|GRUB_ENABLE_CRYPTODISK}} can be used to enable GRUB to ask for a password to open a [[LUKS]] blockdevice in order to read its configuration and load any [[initramfs]] and [[kernel]] from it. This option tries to solve the issue of having an [[Dm-crypt/Specialties#Securing_the_unencrypted_boot_partition|unencrypted boot partition]].<br />
<br />
The feature is enabled by adding: <br />
GRUB_ENABLE_CRYPTODISK=y<br />
to {{ic|/etc/default/grub}}. After this configuration a subsequent run of ''grub-mkconfig'' to [[#Generate the main configuration file]] is required while the encrypted {{ic|/boot}} is mounted. <br />
{{Note|{{ic|1=GRUB_ENABLE_CRYPTODISK=1}} [https://savannah.gnu.org/bugs/?41524 will not work] as opposed to the request shown in GRUB 2.02-beta2.}}<br />
<br />
Depending on the system's setup, note the following: <br />
<br />
* For the feature to work it is not required that {{ic|/boot}} is kept in a separate partition, it may also stay under the system's root {{ic|/}} directory tree.<br />
<br />
* Without further changes you will be prompted twice for a passhrase: the first for GRUB to unlock the {{ic|/boot}} mount point in early boot, the second to unlock the root filesystem itself as described in [[#Root partition]].{{Tip|See [[Dm-crypt/Device encryption#With a keyfile embedded in the initramfs]] for a workaround.}}<br />
<br />
* In order to perform system updates involving the {{ic|/boot}} mount point, it must be ensured that the encrypted {{ic|/boot}} is unlocked to be re-mounted by the initramfs and kernel during boot. With a separate {{ic|/boot}} partition, this may be accomplished by adding an entry to {{ic|/etc/crypttab}} with a keyfile. See [[Dm-crypt/System configuration#crypttab]].<br />
<br />
* If you use a special keymap, a default GRUB installation will not know it. This is relevant for how to enter the passphrase to unlock the LUKS blockdevice.<br />
<br />
* If you experience issues getting the prompt for a password to display (errors regarding cryptouuid, cryptodisk, or "device not found"), try reinstalling grub as below appending the following to the end of your installation command:<br />
<br />
grub-install --target=x86_64-efi --efi-directory=$esp --bootloader-id=grub --recheck '''--modules="part_gpt part_msdos"'''<br />
<br />
== Using the command shell ==<br />
<br />
Since the MBR is too small to store all GRUB modules, only the menu and a few basic commands reside there. The majority of GRUB functionality remains in modules in {{ic|/boot/grub}}, which are inserted as needed. In error conditions (e.g. if the partition layout changes) GRUB may fail to boot. When this happens, a command shell may appear.<br />
<br />
GRUB offers multiple shells/prompts. If there is a problem reading the menu but the bootloader is able to find the disk, you will likely be dropped to the "normal" shell:<br />
grub><br />
<br />
If there is a more serious problem (e.g. GRUB cannot find required files), you may instead be dropped to the "rescue" shell:<br />
grub rescue><br />
<br />
The rescue shell is a restricted subset of the normal shell, offering much less functionality. If dumped to the rescue shell, first try inserting the "normal" module, then starting the "normal" shell:<br />
grub rescue> set prefix=(hdX,Y)/boot/grub<br />
grub rescue> insmod (hdX,Y)/boot/grub/i386-pc/normal.mod<br />
rescue:grub> normal<br />
<br />
=== Pager support ===<br />
<br />
GRUB supports pager for reading commands that provide long output (like the {{ic|help}} command). This works only in normal shell mode and not in rescue mode. To enable pager, in GRUB command shell type:<br />
sh:grub> set pager=1<br />
<br />
=== Using the command shell environment to boot operating systems ===<br />
<br />
grub><br />
<br />
The GRUB's command shell environment can be used to boot operating systems.<br />
A common scenario may be to boot Windows / Linux stored on a drive/partition via '''chainloading'''.<br />
<br />
''Chainloading'' means to load another boot-loader from the current one, ie, chain-loading.<br />
<br />
The other bootloader may be embedded at the starting of the disk(MBR) or at the starting of a partition.<br />
<br />
==== Chainloading a partition ====<br />
<br />
set root=(hdX,Y)<br />
chainloader +1<br />
boot<br />
<br />
X=0,1,2...<br />
Y=1,2,3...<br />
<br />
For example to chainload Windows stored in the first partiton of the first hard disk,<br />
<br />
set root=(hd0,1)<br />
chainloader +1<br />
boot<br />
<br />
Similarly GRUB installed to a partition can be chainloaded.<br />
<br />
==== Chainloading a disk/drive ====<br />
<br />
set root=hdX<br />
chainloader +1<br />
boot<br />
<br />
==== Chainloading Windows/Linux installed in UEFI mode ====<br />
<br />
insmod ntfs<br />
set root=(hd0,gpt4)<br />
chainloader (${root})/EFI/Microsoft/Boot/bootmgfw.efi<br />
boot<br />
<br />
''insmod ntfs'' used for loading the ntfs file system module for loading Windows.<br />
(hd0,gpt4) or /dev/sda4 is my EFI System Partition (ESP).<br />
The entry in the ''chainloader'' line specifies the path of the .efi file to be chain-loaded.<br />
<br />
==== Normal loading ====<br />
<br />
See the examples in [[#Using the rescue console]]<br />
<br />
=== Using the rescue console ===<br />
<br />
See [[#Using the command shell]] first. If unable to activate the standard shell, one possible solution is to boot using a live CD or some other rescue disk to correct configuration errors and reinstall GRUB. However, such a boot disk is not always available (nor necessary); the rescue console is surprisingly robust.<br />
<br />
The available commands in GRUB rescue include {{ic|insmod}}, {{ic|ls}}, {{ic|set}}, and {{ic|unset}}. This example uses {{ic|set}} and {{ic|insmod}}. {{ic|set}} modifies variables and {{ic|insmod}} inserts new modules to add functionality.<br />
<br />
Before starting, the user must know the location of their {{ic|/boot}} partition (be it a separate partition, or a subdirectory under their root):<br />
<br />
grub rescue> set prefix=(hdX,Y)/boot/grub<br />
<br />
where X is the physical drive number and Y is the partition number.<br />
<br />
To expand console capabilities, insert the {{ic|linux}} module:<br />
grub rescue> insmod i386-pc/linux.mod<br />
<br />
{{Note|With a separate boot partition, omit {{ic|/boot}} from the path, (i.e. type {{ic|1=set prefix=(hdX,Y)/grub}}).}}<br />
<br />
This introduces the {{ic|linux}} and {{ic|initrd}} commands, which should be familiar.<br />
<br />
An example, booting Arch Linux:<br />
<br />
set root=(hd0,5)<br />
linux /boot/vmlinuz-linux root=/dev/sda5<br />
initrd /boot/initramfs-linux.img<br />
boot<br />
<br />
With a separate boot partition, again change the lines accordingly:<br />
<br />
set root=(hd0,5)<br />
linux /vmlinuz-linux root=/dev/sda6<br />
initrd /initramfs-linux.img<br />
boot<br />
<br />
{{Note|If you experienced {{ic|error: premature end of file /YOUR_KERNEL_NAME}} during execution of {{ic|linux}} command, you can try {{ic|linux16}} instead.}}<br />
<br />
After successfully booting the Arch Linux installation, users can correct {{ic|grub.cfg}} as needed and then reinstall GRUB.<br />
<br />
To reinstall GRUB and fix the problem completely, changing {{ic|/dev/sda}} if needed. See [[#Installation]] for details.<br />
<br />
== Troubleshooting ==<br />
<br />
=== Intel BIOS not booting GPT ===<br />
<br />
==== MBR ====<br />
<br />
Some Intel BIOS's require at least one bootable MBR partition to be present at boot, causing GPT-partitioned boot setups to be unbootable.<br />
<br />
This can be circumvented by using (for instance) fdisk to mark one of the GPT partitions (preferably the 1007 KiB partition you have created for GRUB already) bootable in the MBR. This can be achieved, using fdisk, by the following commands: Start fdisk against the disk you are installing, for instance {{ic|fdisk /dev/sda}}, then press {{ic|a}} and select the partition you wish to mark as bootable (probably #1) by pressing the corresponding number, finally press {{ic|w}} to write the changes to the MBR.<br />
<br />
{{Note|The bootable-marking must be done in {{ic|fdisk}} or similar, not in GParted or others, as they will not set the bootable flag in the MBR.}}<br />
<br />
With cfdisk, the steps are similar, just {{ic|cfdisk /dev/sda}}, choose bootable (at the left) in the desired hard disk, and quit saving.<br />
<br />
More information is available [http://www.rodsbooks.com/gdisk/bios.html here]<br />
<br />
==== EFI path ====<br />
<br />
Some UEFI firmwares require a bootable file at a known location before they will show UEFI NVRAM boot entries. If this is the case, {{ic|grub-install}} will claim {{ic|efibootmgr}} has added an entry to boot GRUB, however the entry will not show up in the VisualBIOS boot order selector. The solution is to place a file at one of the known locations. Assuming the EFI partition is at {{ic|/boot/efi/}} this will work:<br />
<br />
mkdir /boot/efi/EFI/boot<br />
cp /boot/efi/EFI/grub/grubx64.efi /boot/efi/EFI/boot/bootx64.efi<br />
<br />
This solution worked for an Intel DH87MC motherboard with firmware dated Jan 2014.<br />
<br />
=== Enable debug messages ===<br />
<br />
{{Note|This change is overwritten when [[#Generate the main configuration file]].}}<br />
<br />
Add:<br />
<br />
set pager=1<br />
set debug=all<br />
<br />
to {{ic|grub.cfg}}.<br />
<br />
=== "No suitable mode found" error ===<br />
<br />
If you get this error when booting any menuentry:<br />
<br />
error: no suitable mode found<br />
Booting however<br />
<br />
Then you need to initialize GRUB graphical terminal ({{ic|gfxterm}}) with proper video mode ({{ic|gfxmode}}) in GRUB. This video mode is passed by GRUB to the linux kernel via 'gfxpayload'. In case of UEFI systems, if the GRUB video mode is not initialized, no kernel boot messages will be shown in the terminal (atleast until KMS kicks in).<br />
<br />
Copy {{ic|/usr/share/grub/unicode.pf2}} to ${GRUB_PREFIX_DIR} ({{ic|/boot/grub/}} in case of BIOS and UEFI systems). If GRUB UEFI was installed with {{ic|1=--boot-directory=$esp/EFI}} set, then the directory is {{ic|$esp/EFI/grub/}}:<br />
<br />
# cp /usr/share/grub/unicode.pf2 ${GRUB_PREFIX_DIR}<br />
<br />
If {{ic|/usr/share/grub/unicode.pf2}} does not exist, install {{Pkg|bdf-unifont}}, create the {{ic|unifont.pf2}} file and then copy it to {{ic|${GRUB_PREFIX_DIR<nowiki>}</nowiki>}}:<br />
<br />
# grub-mkfont -o unicode.pf2 /usr/share/fonts/misc/unifont.bdf<br />
<br />
Then, in the {{ic|grub.cfg}} file, add the following lines to enable GRUB to pass the video mode correctly to the kernel, without of which you will only get a black screen (no output) but booting (actually) proceeds successfully without any system hang.<br />
<br />
BIOS systems:<br />
<br />
insmod vbe<br />
<br />
UEFI systems:<br />
<br />
insmod efi_gop<br />
insmod efi_uga<br />
<br />
After that add the following code (common to both BIOS and UEFI):<br />
<br />
insmod font<br />
<br />
if loadfont ${prefix}/fonts/unicode.pf2<br />
then<br />
insmod gfxterm<br />
set gfxmode=auto<br />
set gfxpayload=keep<br />
terminal_output gfxterm<br />
fi<br />
<br />
As you can see for gfxterm (graphical terminal) to function properly, {{ic|unicode.pf2}} font file should exist in {{ic|${GRUB_PREFIX_DIR<nowiki>}</nowiki>}}.<br />
<br />
=== msdos-style error message ===<br />
<br />
grub-setup: warn: This msdos-style partition label has no post-MBR gap; embedding will not be possible!<br />
grub-setup: warn: Embedding is not possible. GRUB can only be installed in this setup by using blocklists.<br />
However, blocklists are UNRELIABLE and its use is discouraged.<br />
grub-setup: error: If you really want blocklists, use --force.<br />
<br />
This error may occur when you try installing GRUB in a VMware container. Read more about it [https://bbs.archlinux.org/viewtopic.php?pid=581760#p581760 here]. It happens when the first partition starts just after the MBR (block 63), without the usual space of 1 MiB (2048 blocks) before the first partition. Read [[#Master Boot Record (MBR) specific instructions]]<br />
<br />
=== UEFI ===<br />
<br />
==== Common installation errors ====<br />
<br />
* If you have a problem when running grub-install with sysfs or procfs and it says you must run {{ic|modprobe efivars}}, try [[Unified Extensible Firmware Interface#Switch to efivarfs]].<br />
* Without {{ic|--target}} or {{ic|--directory}} option, grub-install cannot determine for which firmware to install. In such cases {{ic|grub-install}} will print {{ic|source_dir does not exist. Please specify --target or --directory}}.<br />
* If after running grub-install you are told your partition does not look like an EFI partition then the partition is most likely not {{ic|Fat32}}.<br />
<br />
==== Drop to rescue shell ====<br />
<br />
If GRUB loads but drops you into the rescue shell with no errors, it may be because of a missing or misplaced {{ic|grub.cfg}}. This will happen if GRUB UEFI was installed with {{ic|--boot-directory}} and {{ic|grub.cfg}} is missing OR if the partition number of the boot partition changed (which is hard-coded into the {{ic|grubx64.efi}} file).<br />
<br />
==== GRUB UEFI not loaded ====<br />
<br />
An example of a working EFI:<br />
<br />
{{hc|# efibootmgr -v|<br />
BootCurrent: 0000<br />
Timeout: 3 seconds<br />
BootOrder: 0000,0001,0002<br />
Boot0000* Grub HD(1,800,32000,23532fbb-1bfa-4e46-851a-b494bfe9478c)File(\efi\grub\grub.efi)<br />
Boot0001* Shell HD(1,800,32000,23532fbb-1bfa-4e46-851a-b494bfe9478c)File(\EfiShell.efi)<br />
Boot0002* Festplatte BIOS(2,0,00)P0: SAMSUNG HD204UI<br />
}}<br />
<br />
If the screen only goes black for a second and the next boot option is tried afterwards, according to [https://bbs.archlinux.org/viewtopic.php?pid=981560#p981560 this post], moving GRUB to the partition root can help. The boot option has to be deleted and recreated afterwards. The entry for GRUB should look like this then:<br />
<br />
Boot0000* Grub HD(1,800,32000,23532fbb-1bfa-4e46-851a-b494bfe9478c)File(\grub.efi)<br />
<br />
=== Invalid signature ===<br />
<br />
If trying to boot Windows results in an "invalid signature" error, e.g. after reconfiguring partitions or adding additional hard drives, (re)move GRUB's device configuration and let it reconfigure:<br />
<br />
# mv /boot/grub/device.map /boot/grub/device.map-old<br />
# grub-mkconfig -o /boot/grub/grub.cfg<br />
<br />
{{ic|grub-mkconfig}} should now mention all found boot options, including Windows. If it works, remove {{ic|/boot/grub/device.map-old}}.<br />
<br />
=== Boot freezes ===<br />
<br />
If booting gets stuck without any error message after GRUB loading the kernel and the initial ramdisk, try removing the {{ic|add_efi_memmap}} kernel parameter.<br />
<br />
=== Arch not found from other OS ===<br />
<br />
Some have reported that other distributions have trouble finding Arch Linux automatically with {{ic|os-prober}}. If this problem arises, it has been reported that detection can be improved with the presence of {{ic|/etc/lsb-release}}. This file and updating tool is available with the package {{Pkg|lsb-release}} in the [[official repositories]].<br />
<br />
=== Warning when installing in chroot ===<br />
<br />
When installing GRUB on a LVM system in a chroot environment (e.g. during system installation), you may receive warnings like {{ic|/run/lvm/lvmetad.socket: connect failed: No such file or directory}} or {{ic|WARNING: failed to connect to lvmetad: No such file or directory. Falling back to internal scanning.}} This is because {{ic|/run}} is not available inside the chroot. These warnings will not prevent the system from booting, provided that everything has been done correctly, so you may continue with the installation.<br />
<br />
=== GRUB loads slowly ===<br />
<br />
GRUB can take a long time to load when disk space is low. Check if you have sufficient free disk space on your {{ic|/boot}} or {{ic|/}} partition when you are having problems.<br />
<br />
=== error: unknown filesystem ===<br />
GRUB may output {{ic|error: unknown filesystem}} and refuse to boot for a few reasons. If you are certain that all [[UUID]]s are correct and all filesystems are valid and supported, it may be because your [[#GUID_Partition_Table_.28GPT.29_specific_instructions|BIOS Boot Partition]] is located outside the first 2TB of the drive [https://bbs.archlinux.org/viewtopic.php?id=195948]. Use a partitioning tool of your choice to ensure this partition is located fully within the first 2TB, then reinstall and reconfigure GRUB.<br />
<br />
=== grub-reboot not resetting ===<br />
<br />
GRUB seems to be unable to write to root BTRFS partitions [https://bbs.archlinux.org/viewtopic.php?id=166131]. If you use grub-reboot to boot into another entry it will therefore be unable to update its on-disk environment. Either run grub-reboot from the other entry (for example when switching between various distributions) or consider a different file system. You can reset a "sticky" entry by executing {{ic|grub-editenv create}} and setting {{ic|GRUB_DEFAULT<nowiki>=</nowiki>0}} in your {{ic|/etc/default/grub}} (don't forget {{ic|grub-mkconfig}}).<br />
<br />
=== Old BTRFS prevents installation ===<br />
<br />
If a drive is formatted with BTRFS without creating a partition table (eg. /dev/sdx), then later has partition table written to, there are parts of the BTRFS format that persist. Most utilities and OS's do not see this, but GRUB will refuse to install, even with --force<br />
<br />
# grub-install: warning: Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet..<br />
# grub-install: error: filesystem `btrfs' doesn't support blocklists.<br />
<br />
You can zero the drive, but the easy solution that leaves your data alone is to erase the BTRFS superblock with {{ic|wipefs -o 0x10040 /dev/sdx}}<br />
<br />
== See also ==<br />
<br />
* Official GRUB Manual - https://www.gnu.org/software/grub/manual/grub.html<br />
* Ubuntu wiki page for GRUB - https://help.ubuntu.com/community/Grub2<br />
* GRUB wiki page describing steps to compile for UEFI systems - https://help.ubuntu.com/community/UEFIBooting<br />
* Wikipedia's page on [[Wikipedia:BIOS Boot partition|BIOS Boot partition]]<br />
* http://members.iinet.net/~herman546/p20/GRUB2%20Configuration%20File%20Commands.html - quite complete description of how to configure GRUB</div>Stbinanhttps://wiki.archlinux.org/index.php?title=GRUB&diff=416380GRUB2016-01-20T18:06:16Z<p>Stbinan: /* GNU/Linux menu entry */</p>
<hr />
<div>[[Category:Boot loaders]]<br />
[[ar:GRUB]]<br />
[[cs:GRUB]]<br />
[[de:GRUB]]<br />
[[el:GRUB]]<br />
[[es:GRUB]]<br />
[[fr:GRUB]]<br />
[[he:GRUB]]<br />
[[id:GRUB]]<br />
[[it:GRUB]]<br />
[[ja:GRUB]]<br />
[[nl:GRUB]]<br />
[[pt:GRUB]]<br />
[[ru:GRUB]]<br />
[[tr:GRUB2]]<br />
[[uk:GRUB]]<br />
[[zh-cn:GRUB]]<br />
[[zh-tw:GRUB]]<br />
{{Related articles start}}<br />
{{Related|Arch boot process}}<br />
{{Related|Boot loaders}}<br />
{{Related|Master Boot Record}}<br />
{{Related|GUID Partition Table}}<br />
{{Related|Unified Extensible Firmware Interface}}<br />
{{Related|GRUB Legacy}}<br />
{{Related|GRUB/EFI examples}}<br />
{{Related|GRUB/Tips and tricks}}<br />
{{Related articles end}}<br />
[https://www.gnu.org/software/grub/ GRUB] — not to be confused with [[GRUB Legacy]] — is the next generation of the GRand Unified Bootloader. GRUB is derived from [http://www.nongnu.org/pupa/ PUPA] which was a research project to develop the next generation of what is now GRUB Legacy. GRUB has been rewritten from scratch to clean up everything and provide modularity and portability [https://www.gnu.org/software/grub/grub-faq.html#q1].<br />
<br />
== Preface ==<br />
<br />
* A ''bootloader'' is the first software program that runs when a computer starts. It is responsible for loading and transferring control to the Linux kernel. The kernel, in turn, initializes the rest of the operating system.<br />
* The name ''GRUB'' officially refers to version ''2'' of the software, see [https://www.gnu.org/software/grub/]. If you are looking for the article on the legacy version, see [[GRUB Legacy]].<br />
* GRUB supports [[Btrfs]] as root (without a separate {{ic|/boot}} file system) compressed with either zlib or LZO<br />
** GRUB currently (Sep 2015) supports booting from [[Btrfs]] RAID 0/1/10, but ''not'' RAID 5/6. You may use [[mdadm]] for RAID 5/6, which is supported by GRUB.<br />
* GRUB does not support [[F2FS]] as root so you will need a separate {{ic|/boot}} with a supported file system.<br />
<br />
== BIOS systems ==<br />
<br />
=== GUID Partition Table (GPT) specific instructions ===<br />
<br />
On a BIOS/[[GPT]] configuration a [http://www.gnu.org/software/grub/manual/html_node/BIOS-installation.html BIOS boot partition] is required. GRUB embeds its {{ic|core.img}} into this partition.<br />
<br />
{{Note|<br />
* Before attempting this method keep in mind that not all systems will be able to support this partitioning scheme, read more on [[GUID Partition Table#BIOS systems|GUID partition tables]].<br />
* This additional partition is only needed on a GRUB, BIOS/GPT partitioning scheme. Previously, for a GRUB, BIOS/MBR partitioning scheme, GRUB used the Post-MBR gap for the embedding the {{ic|core.img}}). GRUB for GPT, however, does not use the Post-GPT gap to conform to GPT specifications that require 1_megabyte/2048_sector disk boundaries.<br />
* For [[UEFI]] systems this extra partition is not required as no embedding of boot sectors takes place in that case.<br />
}}<br />
<br />
Create a mebibyte partition ({{ic|1=+1M}} with {{ic|fdisk}} or {{ic|gdisk}}) on the disk with no file system and type BIOS boot (''BIOS boot'' in fdisk, {{ic|ef02}} in gdisk, {{ic|bios_grub}} in {{ic|parted}}). This partition can be in any position order but has to be on the first 2 TiB of the disk. This partition needs to be created before GRUB installation. When the partition is ready, install the bootloader as per the instructions below.<br />
<br />
The post-GPT gap can also be used as the BIOS boot partition though it will be out of GPT alignment specification. Since the partition will not be regularly accessed performance issues can be disregarded (though some disk utilities will display a warning about it). In {{ic|fdisk}} or {{ic|gdisk}} create a new partition starting at sector 34 and spanning to 2047 and set the type. To have the viewable partitions begin at the base consider adding this partition last.<br />
<br />
=== Master Boot Record (MBR) specific instructions ===<br />
<br />
Usually the post-[[MBR]] gap (after the 512 byte MBR region and before the start of the first partition) in many MBR (or 'msdos' disklabel) partitioned systems is 31 KiB when DOS compatibility cylinder alignment issues are satisfied in the partition table. However a post-MBR gap of about 1 to 2 MiB is recommended to provide sufficient room for embedding GRUB's {{ic|core.img}} ({{bug|24103}}). It is advisable to use a partitioning tool that supports 1 MiB partition alignment to obtain this space as well as to satisfy other non-512 byte sector issues (which are unrelated to embedding of {{ic|core.img}}).<br />
<br />
=== Installation ===<br />
<br />
[[Install]] the {{Pkg|grub}} package. It will replace {{AUR|grub-legacy}}, where already installed.<br />
<br />
{{Note|Simply installing the package will not update the {{ic|/boot/grub/i386-pc/core.img}} file and the GRUB modules in {{ic|/boot/grub/i386-pc}}. You need to update them manually using {{ic|grub-install}} as explained below.}}<br />
<br />
==== Install boot files ====<br />
<br />
There are 4 ways to install GRUB boot files in BIOS booting:<br />
<br />
* [[#Install to disk|Install to disk]] (recommended)<br />
* [[#Install to external USB stick|Install to external USB stick]] (for recovery)<br />
* [[#Install to partition or partitionless disk|Install to partition or partitionless disk]] (not recommended)<br />
* [[#Generate core.img alone|Generate core.img alone]] (safest method, but requires another BIOS bootloader like [[Syslinux]] to be installed to chainload {{ic|/boot/grub/i386-pc/core.img}})<br />
<br />
{{Note|See https://www.gnu.org/software/grub/manual/html_node/BIOS-installation.html for additional documentation.}}<br />
<br />
===== Install to disk =====<br />
<br />
{{Note|The method is specific to installing GRUB to a partitioned (MBR or GPT) disk, with GRUB files installed to {{ic|/boot/grub}} and its first stage code installed to the 440-byte MBR boot code region (not to be confused with MBR partition table). }}<br />
<br />
The following commands will:<br />
* Set up GRUB in the 440-byte Master Boot Record boot code region<br />
* Populate the {{ic|/boot/grub}} directory<br />
* Generate the {{ic|/boot/grub/i386-pc/core.img}} file<br />
* Embed it in the 31 KiB (minimum size - varies depending on partition alignment) post-MBR gap in case of MBR partitioned disk<br />
* In the case of a GPT partitioned disk it will embed it in the BIOS Boot Partition , denoted by {{ic|bios_grub}} flag in parted and EF02 type code in gdisk<br />
<br />
# grub-install --recheck --target=i386-pc /dev/sd''x''<br />
# grub-mkconfig -o /boot/grub/grub.cfg<br />
<br />
If you use [[LVM]] for your {{ic|/boot}}, you can install GRUB on multiple physical disks.<br />
<br />
===== Install to external USB stick =====<br />
<br />
Assume your USB stick's first partition is FAT32 and its partition is /dev/sdy1<br />
<br />
# mkdir -p /mnt/usb ; mount /dev/sdy1 /mnt/usb<br />
# grub-install --target=i386-pc --recheck --debug --boot-directory=/mnt/usb/boot /dev/sdy<br />
# grub-mkconfig -o /mnt/usb/boot/grub/grub.cfg<br />
<br />
# optional, backup config files of grub.cfg<br />
# mkdir -p /mnt/usb/etc/default<br />
# cp /etc/default/grub /mnt/usb/etc/default<br />
# cp -a /etc/grub.d /mnt/usb/etc<br />
<br />
# sync; umount /mnt/usb<br />
<br />
===== Install to partition or partitionless disk =====<br />
{{Warning|GRUB '''strongly discourages''' installation to a partition boot sector or a partitionless disk as GRUB Legacy or Syslinux does. This setup is prone to breakage, especially during updates, and is '''not supported''' by the Arch developers.}}<br />
<br />
To set up grub to a partition boot sector, to a partitionless disk (also called superfloppy) or to a floppy disk, run (using for example {{ic|/dev/sdaX}} as the {{ic|/boot}} partition):<br />
<br />
# chattr -i /boot/grub/i386-pc/core.img<br />
# grub-install --target=i386-pc --recheck --debug --force /dev/sdaX<br />
# chattr +i /boot/grub/i386-pc/core.img<br />
<br />
{{Note|<br />
* {{ic|/dev/sdaX}} used for example only.<br />
* {{ic|1=--target=i386-pc}} instructs {{ic|grub-install}} to install for BIOS systems only. It is recommended to always use this option to remove ambiguity in ''grub-install''.<br />
}}<br />
<br />
You need to use the {{ic|--force}} option to allow usage of blocklists and should not use {{ic|1=--grub-setup=/bin/true}} (which is similar to simply generating {{ic|core.img}}).<br />
<br />
{{ic|grub-install}} will give out warnings like which should give you the idea of what might go wrong with this approach:<br />
<br />
/sbin/grub-setup: warn: Attempting to install GRUB to a partitionless disk or to a partition. This is a BAD idea.<br />
/sbin/grub-setup: warn: Embedding is not possible. GRUB can only be installed in this setup by using blocklists.<br />
However, blocklists are UNRELIABLE and their use is discouraged.<br />
<br />
Without {{ic|--force}} you may get the below error and {{ic|grub-setup}} will not setup its boot code in the partition boot sector:<br />
<br />
/sbin/grub-setup: error: will not proceed with blocklists<br />
<br />
With {{ic|--force}} you should get:<br />
<br />
Installation finished. No error reported.<br />
<br />
The reason why {{ic|grub-setup}} does not by default allow this is because in case of partition or a partitionless disk is that GRUB relies on embedded blocklists in the partition bootsector to locate the {{ic|/boot/grub/i386-pc/core.img}} file and the prefix directory {{ic|/boot/grub}}. The sector locations of {{ic|core.img}} may change whenever the file system in the partition is being altered (files copied, deleted etc.). For more info, see https://bugzilla.redhat.com/show_bug.cgi?id=728742 and https://bugzilla.redhat.com/show_bug.cgi?id=730915.<br />
<br />
The workaround for this is to set the immutable flag on {{ic|/boot/grub/i386-pc/core.img}} (using {{ic|chattr}} command as mentioned above) so that the sector locations of the {{ic|core.img}} file in the disk is not altered. The immutable flag on {{ic|/boot/grub/i386-pc/core.img}} needs to be set only if GRUB is installed to a partition boot sector or a partitionless disk, not in case of installation to MBR or simple generation of {{ic|core.img}} without embedding any bootsector (mentioned above).<br />
<br />
Unfortunately, the {{ic|grub.cfg}} file that is created will not contain the proper UUID in order to boot, even if it reports no errors. see https://bbs.archlinux.org/viewtopic.php?pid=1294604#p1294604.<br />
In order to fix this issue the following commands:<br />
<br />
# mount /dev/sdxY /mnt #Your root partition.<br />
# mount /dev/sdxZ /mnt/boot #Your boot partition (if you have one).<br />
# arch-chroot /mnt<br />
# pacman -S linux<br />
# grub-mkconfig -o /boot/grub/grub.cfg<br />
<br />
===== Generate core.img alone =====<br />
<br />
To populate the {{ic|/boot/grub}} directory and generate a {{ic|/boot/grub/i386-pc/core.img}} file '''without''' embedding any GRUB bootsector code in the MBR, post-MBR region, or the partition bootsector, add {{ic|1=--grub-setup=/bin/true}} to {{ic|grub-install}}:<br />
<br />
# grub-install --target=i386-pc --grub-setup=/bin/true --recheck --debug /dev/sda<br />
<br />
{{Note|<br />
* {{ic|/dev/sda}} used for example only.<br />
* {{ic|1=--target=i386-pc}} instructs {{ic|grub-install}} to install for BIOS systems only. It is recommended to always use this option to remove ambiguity in grub-install.<br />
}}<br />
<br />
You can then chainload GRUB's {{ic|core.img}} from GRUB Legacy or syslinux as a Linux kernel or as a multiboot kernel (see also [[Syslinux#Chainloading]]).<br />
<br />
== UEFI systems ==<br />
<br />
{{Note|<br />
* It is recommended to read and understand the [[UEFI]], [[GPT]] and [[UEFI Bootloaders]] pages.<br />
* When installing to use UEFI it is important to start the install with your machine in UEFI mode. The Arch Linux install media must be UEFI bootable.<br />
}}<br />
<br />
=== Check if you have GPT and an ESP ===<br />
<br />
An EFI System Partition (ESP) is needed on every disc you want to boot using EFI. GPT is not strictly necessary, but it is highly recommended and is the only method currently supported in this article. If you are installing Arch Linux on an EFI-capable computer with an already-working operating system, like Windows 8 for example, it is very likely that you already have an ESP. To check for GPT and for an ESP, use {{ic|parted}} as root to print the partition table of the disk you want to boot from. (We are calling it {{ic|/dev/sda}}.)<br />
<br />
# parted /dev/sda print<br />
<br />
For GPT, you are looking for "Partition Table: GPT". For EFI, you are looking for a small (512 MiB or less) partition with a vfat file system and the ''boot'' flag enabled. On it, there should be a directory named "EFI". If these criteria are met, this is your ESP. Make note of the partition number. You will need to know which one it is, so you can mount it later on while installing GRUB to it.<br />
<br />
=== Create an ESP ===<br />
<br />
If you do not have an ESP, you will need to create one. See [[UEFI#EFI System Partition]]<br />
<br />
=== Installation ===<br />
<br />
{{Note|UEFI firmware are not implemented consistently by hardware manufacturers. The installation examples provided are intended to work on the widest range of UEFI systems possible. Those experiencing problems despite applying these methods are encouraged to share detailed information for their hardware-specific cases, especially where solving these problems. A [[GRUB/EFI examples]] article has been provided for such cases.}}<br />
<br />
This section assumes you are installing GRUB for x86_64 systems (x86_64-efi). For i686 systems, replace {{ic|x86_64-efi}} with {{ic|i386-efi}} where appropriate.<br />
<br />
Make sure you are in a [[bash]] shell. For example, when booting from the Arch ISO:<br />
<br />
# arch-chroot /mnt /bin/bash<br />
<br />
[[Install]] the packages {{Pkg|grub}} and {{Pkg|efibootmgr}}. ''GRUB'' is the bootloader, ''efibootmgr'' creates bootable {{ic|.efi}} stub entries used by the GRUB installation script.<br />
<br />
The following steps install the GRUB UEFI application to {{ic|'''$esp'''/EFI/grub}}, install its modules to {{ic|/boot/grub/x86_64-efi}}, and place the bootable {{ic|grubx64.efi}} stub in {{ic|'''$esp'''/EFI/grub}}.<br />
<br />
First, tell GRUB to use UEFI, set the boot directory and set the bootloader ID. Change {{ic|$esp}} to your efi partition (usually {{ic|/boot}}):<br />
<br />
# grub-install --target=x86_64-efi --efi-directory='''$esp''' --bootloader-id='''grub''' --recheck<br />
<br />
The {{ic|--bootloader-id}} is what appears in the boot options to identity the GRUB EFI boot option; make sure this is something you will recognize later. The install will create a directory of the same name under {{ic|$esp/EFI/}} where the EFI binary bootloader will be placed. <br />
<br />
After the above install finished the main GRUB directory is located at {{ic|/boot/grub/}}. <br />
<br />
Remember to [[#Generate the main configuration file]] after finalizing further setup dependant [[#Configuration]]. <br />
<br />
{{Note|<br />
* While some distributions require a {{ic|/boot/efi}} or {{ic|/boot/EFI}} directory, Arch does not.<br />
* {{ic|--efi-directory}} and {{ic|--bootloader-id}} are specific to GRUB UEFI. {{ic|--efi-directory}} specifies the mountpoint of the ESP. It replaces {{ic|--root-directory}}, which is deprecated. <br />
* You might note the absence of a <device_path> option (e.g.: {{ic|/dev/sda}}) in the {{ic|grub-install}} command. In fact any <device_path> provided will be ignored by the GRUB install script, as UEFI bootloaders do not use a MBR or partition boot sector at all.<br />
}}<br />
<br />
See [[#UEFI|UEFI troubleshooting]] in case of problems.<br />
<br />
=== Further reading ===<br />
<br />
Below is other relevant information regarding installing Arch via UEFI<br />
<br />
==== Alternative install method ====<br />
<br />
Usually, GRUB keeps all files, including configuration files, in {{ic|/boot}}, regardless of where the EFI System Partition is mounted.<br />
<br />
If you want to keep these files inside the EFI System Partition itself, add {{ic|--boot-directory&#61;$esp}} to the grub-install command:<br />
<br />
# grub-install --target=x86_64-efi --efi-directory=$esp --bootloader-id=grub --boot-directory=$esp --recheck --debug<br />
<br />
This puts all GRUB files in {{ic|$esp/grub}}, instead of in {{ic|/boot/grub}}. When using this method, make sure you have ''grub-mkconfig'' put the configuration file in the same place:<br />
<br />
# grub-mkconfig -o $esp/grub/grub.cfg<br />
<br />
Configuration is otherwise the same.<br />
<br />
==== UEFI firmware workaround ====<br />
<br />
Some UEFI firmware requires that the bootable {{ic|.efi}} stub have a specific name and be placed in a specific location: {{ic|$esp/EFI/boot/bootx64.efi}} (where {{ic|$esp}} is the UEFI partition mountpoint). Failure to do so in such instances will result in an unbootable installation. Fortunately, this will not cause any problems with other firmware that does not require this.<br />
<br />
To do so, first create the necessary directory, and then copy across the grub {{ic|.efi}} stub, renaming it in the process:<br />
<br />
# mkdir $esp/EFI/boot<br />
# cp $esp/EFI/grub_uefi/grubx64.efi $esp/EFI/boot/bootx64.efi<br />
<br />
==== Create a GRUB entry in the firmware boot manager ====<br />
{{ic|grub-install}} automatically tries to create a menu entry in the boot manager. If it does not, then see [[UEFI#efibootmgr]] for instructions to use {{ic|efibootmgr}} to create a menu entry. However, the problem is likely to be that you have not booted your CD/USB in UEFI mode, as in [[UEFI#Create UEFI bootable USB from ISO]].<br />
<br />
==== GRUB standalone ====<br />
<br />
This section assumes you are creating a standalone GRUB for x86_64 systems (x86_64-efi). For i686 systems, replace {{ic|x86_64-efi}} with {{ic|i386-efi}} where appropriate.<br />
<br />
It is possible to create a {{ic|grubx64_standalone.efi}} application which has all the modules embedded in a tar archive within the UEFI application, thus removing the need for having a separate directory populated with all of the GRUB UEFI modules and other related files. This is done using the {{ic|grub-mkstandalone}} command (included in {{Pkg|grub}}) as follows:<br />
<br />
# echo 'configfile ${cmdpath}/grub.cfg' > /tmp/grub.cfg<br />
# grub-mkstandalone -d /usr/lib/grub/x86_64-efi/ -O x86_64-efi --modules="part_gpt part_msdos" --fonts="unicode" --locales="en@quot" --themes="" -o "$esp/EFI/grub/grubx64_standalone.efi" "boot/grub/grub.cfg=/tmp/grub.cfg" -v<br />
<br />
Then copy the GRUB config file to {{ic|$esp/EFI/grub/grub.cfg}} and create a UEFI Boot Manager entry for {{ic|$esp/EFI/grub/grubx64_standalone.efi}} using [[UEFI#efibootmgr|efibootmgr]].<br />
<br />
{{Note|<br />
The option {{ic|1=--modules="part_gpt part_msdos"}} (with the quotes) is necessary for the {{ic|${cmdpath} }} feature to work properly.<br />
}}<br />
<br />
{{Warning|You may find that the {{ic|grub.cfg}} file is not loaded due to {{ic|${cmdpath} }} missing a slash (i.e. {{ic|(hd1,msdos2)EFI/Boot}} instead of {{ic|(hd1,msdos2)/EFI/Boot}}) and so you are dropped into a GRUB shell. If this happens determine what {{ic|${cmdpath} }} is set to ({{ic|echo ${cmdpath} }}) and then load the config file manually (e.g. {{ic|configfile (hd1,msdos2)/EFI/Boot/grub.cfg}}).}}<br />
<br />
==== Technical information ====<br />
<br />
The GRUB EFI file always expects its config file to be at {{ic|${prefix}/grub.cfg}}. However in the standalone GRUB EFI file, the {{ic|${prefix} }} is located inside a tar archive and embedded inside the standalone GRUB EFI file itself (inside the GRUB environment, it is denoted by {{ic|"(memdisk)"}}, without quotes). This tar archive contains all the files that would be stored normally at {{ic|/boot/grub}} in case of a normal GRUB EFI install.<br />
<br />
Due to this embedding of {{ic|/boot/grub}} contents inside the standalone image itself, it does not rely on actual (external) {{ic|/boot/grub}} for anything. Thus in case of standalone GRUB EFI file {{ic|1=${prefix}==(memdisk)/boot/grub}} and the standalone GRUB EFI file reads expects the config file to be at {{ic|1=${prefix}/grub.cfg==(memdisk)/boot/grub/grub.cfg}}.<br />
<br />
Hence to make sure the standalone GRUB EFI file reads the external {{ic|grub.cfg}} located in the same directory as the EFI file (inside the GRUB environment, it is denoted by {{ic|${cmdpath} }}), we create a simple {{ic|/tmp/grub.cfg}} which instructs GRUB to use {{ic|${cmdpath}/grub.cfg}} as its config ({{ic|configfile ${cmdpath}/grub.cfg}} command in {{ic|(memdisk)/boot/grub/grub.cfg}}). We then instruct grub-mkstandalone to copy this {{ic|/tmp/grub.cfg}} file to {{ic|${prefix}/grub.cfg}} (which is actually {{ic|(memdisk)/boot/grub/grub.cfg}}) using the option {{ic|1="boot/grub/grub.cfg=/tmp/grub.cfg"}}.<br />
<br />
This way, the standalone GRUB EFI file and actual {{ic|grub.cfg}} can be stored in any directory inside the EFI System Partition (as long as they are in the same directory), thus making them portable.<br />
<br />
== Generate the main configuration file ==<br />
<br />
After the installation, the main configuration file {{ic|grub.cfg}} needs to be generated. The generation process can be influenced by a variety of options in {{ic|/etc/default/grub}} and scripts in {{ic|/etc/grub.d/}}; see [[#Configuration]]. <br />
<br />
If you have not done additional configuration, the automatic generation will determine the root filesystem of the system to boot for the configuration file. For that to succeed it is important that the system is either booted or chrooted into. <br />
<br />
{{Note|Remember that {{ic|grub.cfg}} has to be re-generated after any change to {{ic|/etc/default/grub}} or files in {{ic|/etc/grub.d/}}.}}<br />
<br />
Use the ''grub-mkconfig'' tool to generate {{ic|grub.cfg}}:<br />
<br />
# grub-mkconfig -o /boot/grub/grub.cfg<br />
<br />
{{Note|<br />
* The default file path is {{ic|/boot/grub/grub.cfg}}, not {{ic|/boot/grub/i386-pc/grub.cfg}}. The {{Pkg|grub}} includes a sample {{ic|/boot/grub/grub.cfg}}; ensure your intended changes were written to this file.<br />
* If you are trying to run ''grub-mkconfig'' in a chroot or ''systemd-nspawn'' container, you might notice that it does not work, complaining that ''grub-probe'' cannot get the "canonical path of /dev/sdaX". In this case, try using ''arch-chroot'' as described in the [https://bbs.archlinux.org/viewtopic.php?pid&#61;1225067#p1225067 BBS post].<br />
}}<br />
<br />
By default the generation scripts automatically add menu entries for Arch Linux to any generated configuration. See [[#Dual-booting]] for configuration with other systems.<br />
<br />
== Configuration ==<br />
<br />
This section only covers editing the {{ic|/etc/default/grub}} configuration file. See [[GRUB/Tips and tricks]] for more information.<br />
<br />
Remember to always [[#Generate the main configuration file]] after making changes to {{ic|/etc/default/grub}}.<br />
<br />
=== Additional arguments ===<br />
<br />
To pass custom additional arguments to the Linux image, you can set the {{ic|GRUB_CMDLINE_LINUX}} + {{ic|GRUB_CMDLINE_LINUX_DEFAULT}} variables in {{ic|/etc/default/grub}}. The two are appended to each other and passed to kernel when generating regular boot entries. For the ''recovery'' boot entry, only {{ic|GRUB_CMDLINE_LINUX}} is used in the generation.<br />
<br />
It is not necessary to use both, but can be useful. For example, you could use {{ic|<nowiki>GRUB_CMDLINE_LINUX_DEFAULT="resume=/dev/sdaX</nowiki> quiet"}} where {{ic|sda'''X'''}} is your swap partition to enable resume after hibernation. This would generate a recovery boot entry without the resume and without ''quiet'' suppressing kernel messages during a boot from that menu entry. Though, the other (regular) menu entries would have them as options.<br />
<br />
By default ''grub-mkconfig'' determines the [[UUID]] of the root filesystem for the configuration. To disable this, uncomment {{ic|1=GRUB_DISABLE_LINUX_UUID=true}}. <br />
<br />
For generating the GRUB recovery entry you also have to comment out {{ic|<nowiki>#GRUB_DISABLE_RECOVERY=true</nowiki>}} in {{ic|/etc/default/grub}}.<br />
<br />
You can also use {{ic|<nowiki>GRUB_CMDLINE_LINUX="resume=UUID=uuid-of-swap-partition"</nowiki>}}<br />
<br />
See [[Kernel parameters]] for more info.<br />
<br />
=== Dual-booting ===<br />
<br />
{{Tip|To have ''grub-mkconfig'' search for other installed systems, [[install]] {{Pkg|os-prober}}.}}<br />
<br />
==== Automatically generating using /etc/grub.d/40_custom and grub-mkconfig ====<br />
<br />
The best way to add other entries is editing the {{ic|/etc/grub.d/40_custom}} or {{ic|/boot/grub/custom.cfg}}. The entries in this file will be automatically added when running {{ic|grub-mkconfig}}.<br />
After adding the new lines, run:<br />
{{bc|<nowiki># grub-mkconfig -o /boot/grub/grub.cfg</nowiki>}}<br />
or, for UEFI-GPT Mode (As per [[#Alternative install method]]):<br />
{{bc|<nowiki># grub-mkconfig -o /boot/efi/EFI/GRUB/grub.cfg</nowiki>}}<br />
to generate an updated {{ic|grub.cfg}}.<br />
<br />
For example, a typical {{ic|/etc/grub.d/40_custom}} file, could appear similar to the following one, created for [http://h10025.www1.hp.com/ewfrf/wc/product?cc=us&destPage=product&lc=en&product=5402703&tmp_docname= HP Pavilion 15-e056sl Notebook PC], originally with Microsoft Windows 8 preinstalled. Each {{ic|menuentry}} should maintain a structure similar to the following ones. Note that the UEFI partition {{ic|/dev/sda2}} within GRUB is called {{ic|hd0,gpt2}} and {{ic|ahci0,gpt2}} (see [[#Windows installed in UEFI-GPT Mode menu entry|here]] for more info).<br />
<br />
{{hc|/etc/grub.d/40_custom|<nowiki>#!/bin/sh<br />
exec tail -n +3 $0<br />
# This file provides an easy way to add custom menu entries.&nbsp; Simply type the<br />
# menu entries you want to add after this comment.&nbsp; Be careful not to change<br />
# the 'exec tail' line above.<br />
<br />
menuentry "HP / Microsoft Windows 8.1" {<br />
echo "Loading HP / Microsoft Windows 8.1..."<br />
insmod part_gpt<br />
insmod fat<br />
insmod search_fs_uuid<br />
insmod chain<br />
search --fs-uuid --no-floppy --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 763A-9CB6<br />
chainloader /EFI/Microsoft/Boot/bootmgfw.efi<br />
}<br />
<br />
menuentry "HP / Microsoft Control Center" {<br />
echo "Loading HP / Microsoft Control Center..."<br />
insmod part_gpt<br />
insmod fat<br />
insmod search_fs_uuid<br />
insmod chain<br />
search --fs-uuid --no-floppy --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 763A-9CB6<br />
chainloader /EFI/HP/boot/bootmgfw.efi<br />
}<br />
<br />
menuentry "System shutdown" {<br />
echo "System shutting down..."<br />
halt<br />
}<br />
<br />
menuentry "System restart" {<br />
echo "System rebooting..."<br />
reboot<br />
}</nowiki>}}<br />
<br />
===== GNU/Linux menu entry =====<br />
Assuming that the other distro is on partition {{ic|sda2}}:<br />
<br />
{{bc|<nowiki>menuentry "Other Linux" {<br />
set root=(hd0,2)<br />
linux /boot/vmlinuz (add other options here as required)<br />
initrd /boot/initrd.img (if the other kernel uses/needs one)<br />
}</nowiki>}}<br />
<br />
Alternatively let grub search for the right partition by ''UUID'' or ''label'':<br />
<br />
{{bc|<nowiki>menuentry "Other Linux" {<br />
# assuming that UUID is 763A-9CB6<br />
search --set=root --fs-uuid 763A-9CB6<br />
<br />
# search by label OTHER_LINUX (make sure that partition label is unambiguous)<br />
#search --set=root --label OTHER_LINUX<br />
<br />
linux /boot/vmlinuz (add other options here as required, for example: root=UUID=763A-9CB6)<br />
initrd /boot/initrd.img (if the other kernel uses/needs one)<br />
}</nowiki>}}<br />
<br />
For some os like Nix OS and GuixSD, because the kernel doesn't get patched and is in a special place named store, the entry will be a bit different, below it's an example for GuixSD:<br />
<br />
{{bc|<nowiki>menuentry "GNU with Linux-Libre 4.2.5 (alpha)" {<br />
search --set=root --fs-uuid YOUR_ROOT_PARTITION_UUID<br />
search --file --set /gnu/store/zbm09fk0wxkw2wyygnn4gcfxj8s31ajd-linux-libre-4.2.5/bzImage<br />
<br />
linux /gnu/store/zbm09fk0wxkw2wyygnn4gcfxj8s31ajd-linux-libre-4.2.5/bzImage --root=YOUR_ROOT_PARTITION_LABEL --system=/gnu/store/a1brgzara5mw72jnmhqjx0j69ah8p5mp-system --load=/gnu/store/a1brgzara5mw72jnmhqjx0j69ah8p5mp-system/boot<br />
initrd /gnu/store/a1brgzara5mw72jnmhqjx0j69ah8p5mp-system/initrd<br />
}</nowiki>}}<br />
<br />
===== FreeBSD menu entry =====<br />
The following three methods require that FreeBSD is installed on a single partition with UFS(v2). Assuming the nested BSD partition table is on {{ic|sda4}}:<br />
<br />
====== Loading the kernel directly ======<br />
{{bc|1=<br />
menuentry 'FreeBSD' {<br />
insmod ufs2<br />
set root='hd0,gpt4,bsd1'<br />
## or 'hd0,msdos4,bsd1', if using an IBM-PC (MS-DOS) style partition table<br />
kfreebsd /boot/kernel/kernel<br />
kfreebsd_loadenv /boot/device.hints<br />
set kFreeBSD.vfs.root.mountfrom=ufs:/dev/ada0s4a<br />
set kFreeBSD.vfs.root.mountfrom.options=rw<br />
}<br />
}}<br />
<br />
====== Chainloading the embedded boot record ======<br />
{{bc|1=<br />
menuentry 'FreeBSD' {<br />
insmod ufs2<br />
set root='hd0,gpt4,bsd1'<br />
chainloader +1<br />
}<br />
}}<br />
<br />
====== Running the traditional BSD 2nd stage loader ======<br />
{{bc|1=<br />
menuentry 'FreeBSD' {<br />
insmod ufs2<br />
set root='(hd0,4)'<br />
kfreebsd /boot/loader<br />
}<br />
}}<br />
<br />
===== Windows XP menu entry=====<br />
This assumes that your Windows partition is {{ic|sda3}}. Remember you need to point set root and chainloader to the system reserve partition that windows made when it installed, not the actual partition windows is on. This example works if your system reserve partition is {{ic|sda3}}.<br />
<br />
{{bc|<nowiki># (2) Windows XP<br />
menuentry "Windows XP" {<br />
set root="(hd0,3)"<br />
chainloader +1<br />
}</nowiki>}}<br />
<br />
If the Windows bootloader is on an entirely different hard drive than GRUB, it may be necessary to trick Windows into believing that it is the first hard drive. This was possible with {{ic|drivemap}}. Assuming GRUB is on {{ic|hd0}} and Windows is on {{ic|hd2}}, you need to add the following after {{ic|set root}}:<br />
<br />
{{bc|drivemap -s hd0 hd2}}<br />
<br />
===== Windows installed in UEFI-GPT Mode menu entry =====<br />
<br />
{{Note|This menuentry will work only in UEFI boot mode and only if the Windows bitness matches the UEFI bitness. It '''WILL NOT WORK''' in BIOS installed GRUB. See [[Dual boot with Windows#Windows UEFI vs BIOS limitations]] and [[Dual boot with Windows#Bootloader UEFI vs BIOS limitations]] for more info.}}<br />
<br />
{{bc|<nowiki>if [ "${grub_platform}" == "efi" ]; then<br />
menuentry "Microsoft Windows Vista/7/8/8.1 UEFI-GPT" {<br />
insmod part_gpt<br />
insmod fat<br />
insmod search_fs_uuid<br />
insmod chain<br />
search --fs-uuid --set=root $hints_string $fs_uuid<br />
chainloader /EFI/Microsoft/Boot/bootmgfw.efi<br />
}<br />
fi</nowiki>}}<br />
<br />
where {{ic|$hints_string}} and {{ic|$fs_uuid}} are obtained with the following two commands. {{ic|$fs_uuid}}'s command:<br />
<br />
{{hc|1=# grub-probe --target=fs_uuid $esp/EFI/Microsoft/Boot/bootmgfw.efi|2=<br />
1ce5-7f28<br />
}}<br />
<br />
{{ic|$hints_string}}'s command:<br />
<br />
{{hc|1=# grub-probe --target=hints_string $esp/EFI/Microsoft/Boot/bootmgfw.efi|2=<br />
--hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1<br />
}}<br />
<br />
These two commands assume the ESP Windows uses is mounted at {{ic|$esp}}. There might be case differences in the path to Windows's EFI file, what with being Windows, and all.<br />
<br />
===== "Shutdown" menu entry =====<br />
<br />
{{bc|<nowiki>menuentry "System shutdown" {<br />
echo "System shutting down..."<br />
halt<br />
}</nowiki>}}<br />
<br />
===== "Restart" menu entry =====<br />
<br />
{{bc|<nowiki>menuentry "System restart" {<br />
echo "System rebooting..."<br />
reboot<br />
}</nowiki>}}<br />
<br />
===== Windows installed in BIOS-MBR mode =====<br />
<br />
{{Poor writing|This section does not fit into the others, should be slimmed down a bit.}}<br />
<br />
{{Note|GRUB supports booting {{ic|bootmgr}} directly and chainload of partition boot sector is no longer required to boot Windows in a BIOS-MBR setup.}}<br />
<br />
{{Warning|It is the '''system partition''' that has {{ic|/bootmgr}}, not your "real" Windows partition (usually C:). In {{ic|blkid}} output, the system partition is the one with {{ic|LABEL&#61;"SYSTEM RESERVED"}} or {{ic|LABEL&#61;"SYSTEM"}} and is only about 100 to 200 MB in size (much like the boot partition for Arch). See [[Wikipedia:System partition and boot partition]] for more info.}}<br />
<br />
Throughout this section, it is assumed your Windows partition is {{ic|/dev/sda1}}. A different partition will change every instance of hd0,msdos1. First, find the UUID of the NTFS file system of the Windows's SYSTEM PARTITION where the {{ic|bootmgr}} and its files reside. For example, if Windows {{ic|bootmgr}} exists at {{ic|/media/SYSTEM_RESERVED/bootmgr}}:<br />
<br />
For Windows Vista/7/8/8.1:<br />
<br />
# grub-probe --target=fs_uuid /media/SYSTEM_RESERVED/bootmgr<br />
69B235F6749E84CE<br />
<br />
# grub-probe --target=hints_string /media/SYSTEM_RESERVED/bootmgr<br />
--hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1<br />
<br />
{{Note|For Windows XP, replace {{ic|bootmgr}} with {{ic|NTLDR}} in the above commands. And note that there may not be a separate SYSTEM_RESERVED partition; just probe the file NTLDR on your Windows partition.}}<br />
<br />
Then, add the below code to {{ic|/etc/grub.d/40_custom}} or {{ic|/boot/grub/custom.cfg}} and regenerate {{ic|grub.cfg}} with {{ic|grub-mkconfig}} as explained above to boot Windows (XP, Vista, 7 or 8) installed in BIOS-MBR mode:<br />
<br />
{{Note|These menuentries will work only in Legacy BIOS boot mode. It WILL NOT WORK in uefi installed grub(2). See [[Dual boot with Windows#Windows UEFI vs BIOS limitations]] and [[Dual boot with Windows#Bootloader UEFI vs BIOS limitations]].}}<br />
<br />
For Windows Vista/7/8/8.1:<br />
<br />
if [ "${grub_platform}" == "pc" ]; then<br />
menuentry "Microsoft Windows Vista/7/8/8.1 BIOS-MBR" {<br />
insmod part_msdos<br />
insmod ntfs<br />
insmod search_fs_uuid<br />
insmod ntldr <br />
search --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 69B235F6749E84CE<br />
ntldr /bootmgr<br />
}<br />
fi<br />
<br />
For Windows XP:<br />
<br />
if [ "${grub_platform}" == "pc" ]; then<br />
menuentry "Microsoft Windows XP" {<br />
insmod part_msdos<br />
insmod ntfs<br />
insmod search_fs_uuid<br />
insmod ntldr <br />
search --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 69B235F6749E84CE<br />
ntldr /ntldr<br />
}<br />
fi<br />
<br />
{{Note|In some cases, mine I have installed GRUB before a clean Windows 8, you cannot boot Windows having an error with {{ic|\boot\bcd}} (error code {{ic|0xc000000f}}). You can fix it going to Windows Recovery Console (cmd from install disk) and executing:<br />
x:\> "bootrec.exe /fixboot" <br />
x:\> "bootrec.exe /RebuildBcd".<br />
Do '''not''' use {{ic|bootrec.exe /Fixmbr}} because it will wipe GRUB out.}}<br />
<br />
{{ic|/etc/grub.d/40_custom}} can be used as a template to create {{ic|/etc/grub.d/nn_custom}}. Where {{ic|nn}} defines the precendence, indicating the order the script is executed. The order scripts are executed determine the placement in the grub boot menu.<br />
<br />
{{Note|{{ic|nn}} should be greater than 06 to ensure necessary scripts are executed first.}}<br />
<br />
==== With Windows via EasyBCD and NeoGRUB ====<br />
<br />
{{Merge|NeoGRUB|New page has been created, so this section should be merged there.}}<br />
<br />
Since EasyBCD's NeoGRUB currently does not understand the GRUB menu format, chainload to it by replacing the contents of your {{ic|C:\NST\menu.lst}} file with lines similar to the following:<br />
<br />
default 0<br />
timeout 1<br />
<br />
title Chainload into GRUB v2<br />
root (hd0,7)<br />
kernel /boot/grub/i386-pc/core.img<br />
<br />
Finally, [[#Generate the main configuration file]].<br />
<br />
==== parttool for hide/unhide ====<br />
<br />
If you have a Windows 9x paradigm with hidden {{ic|C:\}} disks GRUB can hide/unhide it using {{ic|parttool}}. For example, to boot the third {{ic|C:\}} disk of three Windows 9x installations on the CLI enter the CLI and:<br />
parttool hd0,1 hidden+ boot-<br />
parttool hd0,2 hidden+ boot-<br />
parttool hd0,3 hidden- boot+<br />
set root=hd0,3<br />
chainloader +1<br />
boot<br />
<br />
=== LVM ===<br />
<br />
If you use [[LVM]] for your {{ic|/boot}}, make sure that the {{ic|lvm}} module is preloaded:<br />
<br />
{{hc|/etc/default/grub|2=<br />
GRUB_PRELOAD_MODULES="lvm"<br />
}}<br />
<br />
=== RAID ===<br />
<br />
GRUB provides convenient handling of RAID volumes. You need to add {{ic|insmod mdraid}} which allows you to address the volume natively. For example, {{ic|/dev/md0}} becomes:<br />
set root=(md/0)<br />
<br />
whereas a partitioned RAID volume (e.g. {{ic|/dev/md0p1}}) becomes:<br />
set root=(md/0,1)<br />
<br />
To install grub when using RAID1 as the {{ic|/boot}} partition (or using {{ic|/boot}} housed on a RAID1 root partition), on devices with GPT ef02/'BIOS boot partition', simply run ''grub-install'' on both of the drives, such as:<br />
# grub-install --target=i386-pc --recheck --debug /dev/sda<br />
# grub-install --target=i386-pc --recheck --debug /dev/sdb<br />
<br />
Where the RAID 1 array housing {{ic|/boot}} is housed on {{ic|/dev/sda}} and {{ic|/dev/sdb}}.<br />
<br />
=== Multiple entries ===<br />
<br />
For tips on managing multiple GRUB entries, for example when using both {{Pkg|linux}} and {{Pkg|linux-lts}} kernels, see [[GRUB/Tips and tricks#Multiple entries]].<br />
<br />
=== Encryption ===<br />
<br />
==== Root partition ====<br />
<br />
For an encrypted root filesystem, it is necessary to edit {{ic|/etc/default/grub}} with the parameters required to unlock the encrypted filesystem during boot. For example, if the [[mkinitcpio]] {{ic|encrypt}} hook is used, the {{ic|cryptdevice}} parameter must be added to {{ic|GRUB_CMDLINE_LINUX<nowiki>=</nowiki>""}} command. In the example below, the {{ic|sda2}} partition has been encrypted as {{ic|/dev/mapper/cryptroot}}:<br />
<br />
{{hc|/etc/default/grub|2=<br />
GRUB_CMDLINE_LINUX="cryptdevice=/dev/sda2:cryptroot"<br />
}}<br />
<br />
Once {{ic|/etc/default/grub}} has been amended, it will then be necessary to [[#Generate the main configuration file]].<br />
<br />
For further information about bootloader configuration for encrypted devices, see [[Dm-crypt/System configuration#Boot loader]].<br />
<br />
{{Tip|If you are upgrading from a working GRUB Legacy configuration, check {{ic|/boot/grub/menu.lst.pacsave}} for the correct device/label to add. Look for them after the text {{ic|kernel /vmlinuz-linux}}.}}<br />
<br />
==== Boot partition ====<br />
<br />
The GRUB [https://www.gnu.org/software/grub/manual/grub.html#Simple-configuration parameter] {{ic|GRUB_ENABLE_CRYPTODISK}} can be used to enable GRUB to ask for a password to open a [[LUKS]] blockdevice in order to read its configuration and load any [[initramfs]] and [[kernel]] from it. This option tries to solve the issue of having an [[Dm-crypt/Specialties#Securing_the_unencrypted_boot_partition|unencrypted boot partition]].<br />
<br />
The feature is enabled by adding: <br />
GRUB_ENABLE_CRYPTODISK=y<br />
to {{ic|/etc/default/grub}}. After this configuration a subsequent run of ''grub-mkconfig'' to [[#Generate the main configuration file]] is required while the encrypted {{ic|/boot}} is mounted. <br />
{{Note|{{ic|1=GRUB_ENABLE_CRYPTODISK=1}} [https://savannah.gnu.org/bugs/?41524 will not work] as opposed to the request shown in GRUB 2.02-beta2.}}<br />
<br />
Depending on the system's setup, note the following: <br />
<br />
* For the feature to work it is not required that {{ic|/boot}} is kept in a separate partition, it may also stay under the system's root {{ic|/}} directory tree.<br />
<br />
* Without further changes you will be prompted twice for a passhrase: the first for GRUB to unlock the {{ic|/boot}} mount point in early boot, the second to unlock the root filesystem itself as described in [[#Root partition]].{{Tip|See [[Dm-crypt/Device encryption#With a keyfile embedded in the initramfs]] for a workaround.}}<br />
<br />
* In order to perform system updates involving the {{ic|/boot}} mount point, it must be ensured that the encrypted {{ic|/boot}} is unlocked to be re-mounted by the initramfs and kernel during boot. With a separate {{ic|/boot}} partition, this may be accomplished by adding an entry to {{ic|/etc/crypttab}} with a keyfile. See [[Dm-crypt/System configuration#crypttab]].<br />
<br />
* If you use a special keymap, a default GRUB installation will not know it. This is relevant for how to enter the passphrase to unlock the LUKS blockdevice.<br />
<br />
* If you experience issues getting the prompt for a password to display (errors regarding cryptouuid, cryptodisk, or "device not found"), try reinstalling grub as below appending the following to the end of your installation command:<br />
<br />
grub-install --target=x86_64-efi --efi-directory=$esp --bootloader-id=grub --recheck '''--modules="part_gpt part_msdos"'''<br />
<br />
== Using the command shell ==<br />
<br />
Since the MBR is too small to store all GRUB modules, only the menu and a few basic commands reside there. The majority of GRUB functionality remains in modules in {{ic|/boot/grub}}, which are inserted as needed. In error conditions (e.g. if the partition layout changes) GRUB may fail to boot. When this happens, a command shell may appear.<br />
<br />
GRUB offers multiple shells/prompts. If there is a problem reading the menu but the bootloader is able to find the disk, you will likely be dropped to the "normal" shell:<br />
grub><br />
<br />
If there is a more serious problem (e.g. GRUB cannot find required files), you may instead be dropped to the "rescue" shell:<br />
grub rescue><br />
<br />
The rescue shell is a restricted subset of the normal shell, offering much less functionality. If dumped to the rescue shell, first try inserting the "normal" module, then starting the "normal" shell:<br />
grub rescue> set prefix=(hdX,Y)/boot/grub<br />
grub rescue> insmod (hdX,Y)/boot/grub/i386-pc/normal.mod<br />
rescue:grub> normal<br />
<br />
=== Pager support ===<br />
<br />
GRUB supports pager for reading commands that provide long output (like the {{ic|help}} command). This works only in normal shell mode and not in rescue mode. To enable pager, in GRUB command shell type:<br />
sh:grub> set pager=1<br />
<br />
=== Using the command shell environment to boot operating systems ===<br />
<br />
grub><br />
<br />
The GRUB's command shell environment can be used to boot operating systems.<br />
A common scenario may be to boot Windows / Linux stored on a drive/partition via '''chainloading'''.<br />
<br />
''Chainloading'' means to load another boot-loader from the current one, ie, chain-loading.<br />
<br />
The other bootloader may be embedded at the starting of the disk(MBR) or at the starting of a partition.<br />
<br />
==== Chainloading a partition ====<br />
<br />
set root=(hdX,Y)<br />
chainloader +1<br />
boot<br />
<br />
X=0,1,2...<br />
Y=1,2,3...<br />
<br />
For example to chainload Windows stored in the first partiton of the first hard disk,<br />
<br />
set root=(hd0,1)<br />
chainloader +1<br />
boot<br />
<br />
Similarly GRUB installed to a partition can be chainloaded.<br />
<br />
==== Chainloading a disk/drive ====<br />
<br />
set root=hdX<br />
chainloader +1<br />
boot<br />
<br />
==== Chainloading Windows/Linux installed in UEFI mode ====<br />
<br />
insmod ntfs<br />
set root=(hd0,gpt4)<br />
chainloader (${root})/EFI/Microsoft/Boot/bootmgfw.efi<br />
boot<br />
<br />
''insmod ntfs'' used for loading the ntfs file system module for loading Windows.<br />
(hd0,gpt4) or /dev/sda4 is my EFI System Partition (ESP).<br />
The entry in the ''chainloader'' line specifies the path of the .efi file to be chain-loaded.<br />
<br />
==== Normal loading ====<br />
<br />
See the examples in [[#Using the rescue console]]<br />
<br />
=== Using the rescue console ===<br />
<br />
See [[#Using the command shell]] first. If unable to activate the standard shell, one possible solution is to boot using a live CD or some other rescue disk to correct configuration errors and reinstall GRUB. However, such a boot disk is not always available (nor necessary); the rescue console is surprisingly robust.<br />
<br />
The available commands in GRUB rescue include {{ic|insmod}}, {{ic|ls}}, {{ic|set}}, and {{ic|unset}}. This example uses {{ic|set}} and {{ic|insmod}}. {{ic|set}} modifies variables and {{ic|insmod}} inserts new modules to add functionality.<br />
<br />
Before starting, the user must know the location of their {{ic|/boot}} partition (be it a separate partition, or a subdirectory under their root):<br />
<br />
grub rescue> set prefix=(hdX,Y)/boot/grub<br />
<br />
where X is the physical drive number and Y is the partition number.<br />
<br />
To expand console capabilities, insert the {{ic|linux}} module:<br />
grub rescue> insmod i386-pc/linux.mod<br />
<br />
{{Note|With a separate boot partition, omit {{ic|/boot}} from the path, (i.e. type {{ic|1=set prefix=(hdX,Y)/grub}}).}}<br />
<br />
This introduces the {{ic|linux}} and {{ic|initrd}} commands, which should be familiar.<br />
<br />
An example, booting Arch Linux:<br />
<br />
set root=(hd0,5)<br />
linux /boot/vmlinuz-linux root=/dev/sda5<br />
initrd /boot/initramfs-linux.img<br />
boot<br />
<br />
With a separate boot partition, again change the lines accordingly:<br />
<br />
set root=(hd0,5)<br />
linux /vmlinuz-linux root=/dev/sda6<br />
initrd /initramfs-linux.img<br />
boot<br />
<br />
{{Note|If you experienced {{ic|error: premature end of file /YOUR_KERNEL_NAME}} during execution of {{ic|linux}} command, you can try {{ic|linux16}} instead.}}<br />
<br />
After successfully booting the Arch Linux installation, users can correct {{ic|grub.cfg}} as needed and then reinstall GRUB.<br />
<br />
To reinstall GRUB and fix the problem completely, changing {{ic|/dev/sda}} if needed. See [[#Installation]] for details.<br />
<br />
== Troubleshooting ==<br />
<br />
=== Intel BIOS not booting GPT ===<br />
<br />
==== MBR ====<br />
<br />
Some Intel BIOS's require at least one bootable MBR partition to be present at boot, causing GPT-partitioned boot setups to be unbootable.<br />
<br />
This can be circumvented by using (for instance) fdisk to mark one of the GPT partitions (preferably the 1007 KiB partition you have created for GRUB already) bootable in the MBR. This can be achieved, using fdisk, by the following commands: Start fdisk against the disk you are installing, for instance {{ic|fdisk /dev/sda}}, then press {{ic|a}} and select the partition you wish to mark as bootable (probably #1) by pressing the corresponding number, finally press {{ic|w}} to write the changes to the MBR.<br />
<br />
{{Note|The bootable-marking must be done in {{ic|fdisk}} or similar, not in GParted or others, as they will not set the bootable flag in the MBR.}}<br />
<br />
With cfdisk, the steps are similar, just {{ic|cfdisk /dev/sda}}, choose bootable (at the left) in the desired hard disk, and quit saving.<br />
<br />
More information is available [http://www.rodsbooks.com/gdisk/bios.html here]<br />
<br />
==== EFI path ====<br />
<br />
Some UEFI firmwares require a bootable file at a known location before they will show UEFI NVRAM boot entries. If this is the case, {{ic|grub-install}} will claim {{ic|efibootmgr}} has added an entry to boot GRUB, however the entry will not show up in the VisualBIOS boot order selector. The solution is to place a file at one of the known locations. Assuming the EFI partition is at {{ic|/boot/efi/}} this will work:<br />
<br />
mkdir /boot/efi/EFI/boot<br />
cp /boot/efi/EFI/grub/grubx64.efi /boot/efi/EFI/boot/bootx64.efi<br />
<br />
This solution worked for an Intel DH87MC motherboard with firmware dated Jan 2014.<br />
<br />
=== Enable debug messages ===<br />
<br />
{{Note|This change is overwritten when [[#Generate the main configuration file]].}}<br />
<br />
Add:<br />
<br />
set pager=1<br />
set debug=all<br />
<br />
to {{ic|grub.cfg}}.<br />
<br />
=== "No suitable mode found" error ===<br />
<br />
If you get this error when booting any menuentry:<br />
<br />
error: no suitable mode found<br />
Booting however<br />
<br />
Then you need to initialize GRUB graphical terminal ({{ic|gfxterm}}) with proper video mode ({{ic|gfxmode}}) in GRUB. This video mode is passed by GRUB to the linux kernel via 'gfxpayload'. In case of UEFI systems, if the GRUB video mode is not initialized, no kernel boot messages will be shown in the terminal (atleast until KMS kicks in).<br />
<br />
Copy {{ic|/usr/share/grub/unicode.pf2}} to ${GRUB_PREFIX_DIR} ({{ic|/boot/grub/}} in case of BIOS and UEFI systems). If GRUB UEFI was installed with {{ic|1=--boot-directory=$esp/EFI}} set, then the directory is {{ic|$esp/EFI/grub/}}:<br />
<br />
# cp /usr/share/grub/unicode.pf2 ${GRUB_PREFIX_DIR}<br />
<br />
If {{ic|/usr/share/grub/unicode.pf2}} does not exist, install {{Pkg|bdf-unifont}}, create the {{ic|unifont.pf2}} file and then copy it to {{ic|${GRUB_PREFIX_DIR<nowiki>}</nowiki>}}:<br />
<br />
# grub-mkfont -o unicode.pf2 /usr/share/fonts/misc/unifont.bdf<br />
<br />
Then, in the {{ic|grub.cfg}} file, add the following lines to enable GRUB to pass the video mode correctly to the kernel, without of which you will only get a black screen (no output) but booting (actually) proceeds successfully without any system hang.<br />
<br />
BIOS systems:<br />
<br />
insmod vbe<br />
<br />
UEFI systems:<br />
<br />
insmod efi_gop<br />
insmod efi_uga<br />
<br />
After that add the following code (common to both BIOS and UEFI):<br />
<br />
insmod font<br />
<br />
if loadfont ${prefix}/fonts/unicode.pf2<br />
then<br />
insmod gfxterm<br />
set gfxmode=auto<br />
set gfxpayload=keep<br />
terminal_output gfxterm<br />
fi<br />
<br />
As you can see for gfxterm (graphical terminal) to function properly, {{ic|unicode.pf2}} font file should exist in {{ic|${GRUB_PREFIX_DIR<nowiki>}</nowiki>}}.<br />
<br />
=== msdos-style error message ===<br />
<br />
grub-setup: warn: This msdos-style partition label has no post-MBR gap; embedding will not be possible!<br />
grub-setup: warn: Embedding is not possible. GRUB can only be installed in this setup by using blocklists.<br />
However, blocklists are UNRELIABLE and its use is discouraged.<br />
grub-setup: error: If you really want blocklists, use --force.<br />
<br />
This error may occur when you try installing GRUB in a VMware container. Read more about it [https://bbs.archlinux.org/viewtopic.php?pid=581760#p581760 here]. It happens when the first partition starts just after the MBR (block 63), without the usual space of 1 MiB (2048 blocks) before the first partition. Read [[#Master Boot Record (MBR) specific instructions]]<br />
<br />
=== UEFI ===<br />
<br />
==== Common installation errors ====<br />
<br />
* If you have a problem when running grub-install with sysfs or procfs and it says you must run {{ic|modprobe efivars}}, try [[Unified Extensible Firmware Interface#Switch to efivarfs]].<br />
* Without {{ic|--target}} or {{ic|--directory}} option, grub-install cannot determine for which firmware to install. In such cases {{ic|grub-install}} will print {{ic|source_dir does not exist. Please specify --target or --directory}}.<br />
* If after running grub-install you are told your partition does not look like an EFI partition then the partition is most likely not {{ic|Fat32}}.<br />
<br />
==== Drop to rescue shell ====<br />
<br />
If GRUB loads but drops you into the rescue shell with no errors, it may be because of a missing or misplaced {{ic|grub.cfg}}. This will happen if GRUB UEFI was installed with {{ic|--boot-directory}} and {{ic|grub.cfg}} is missing OR if the partition number of the boot partition changed (which is hard-coded into the {{ic|grubx64.efi}} file).<br />
<br />
==== GRUB UEFI not loaded ====<br />
<br />
An example of a working EFI:<br />
<br />
{{hc|# efibootmgr -v|<br />
BootCurrent: 0000<br />
Timeout: 3 seconds<br />
BootOrder: 0000,0001,0002<br />
Boot0000* Grub HD(1,800,32000,23532fbb-1bfa-4e46-851a-b494bfe9478c)File(\efi\grub\grub.efi)<br />
Boot0001* Shell HD(1,800,32000,23532fbb-1bfa-4e46-851a-b494bfe9478c)File(\EfiShell.efi)<br />
Boot0002* Festplatte BIOS(2,0,00)P0: SAMSUNG HD204UI<br />
}}<br />
<br />
If the screen only goes black for a second and the next boot option is tried afterwards, according to [https://bbs.archlinux.org/viewtopic.php?pid=981560#p981560 this post], moving GRUB to the partition root can help. The boot option has to be deleted and recreated afterwards. The entry for GRUB should look like this then:<br />
<br />
Boot0000* Grub HD(1,800,32000,23532fbb-1bfa-4e46-851a-b494bfe9478c)File(\grub.efi)<br />
<br />
=== Invalid signature ===<br />
<br />
If trying to boot Windows results in an "invalid signature" error, e.g. after reconfiguring partitions or adding additional hard drives, (re)move GRUB's device configuration and let it reconfigure:<br />
<br />
# mv /boot/grub/device.map /boot/grub/device.map-old<br />
# grub-mkconfig -o /boot/grub/grub.cfg<br />
<br />
{{ic|grub-mkconfig}} should now mention all found boot options, including Windows. If it works, remove {{ic|/boot/grub/device.map-old}}.<br />
<br />
=== Boot freezes ===<br />
<br />
If booting gets stuck without any error message after GRUB loading the kernel and the initial ramdisk, try removing the {{ic|add_efi_memmap}} kernel parameter.<br />
<br />
=== Arch not found from other OS ===<br />
<br />
Some have reported that other distributions have trouble finding Arch Linux automatically with {{ic|os-prober}}. If this problem arises, it has been reported that detection can be improved with the presence of {{ic|/etc/lsb-release}}. This file and updating tool is available with the package {{Pkg|lsb-release}} in the [[official repositories]].<br />
<br />
=== Warning when installing in chroot ===<br />
<br />
When installing GRUB on a LVM system in a chroot environment (e.g. during system installation), you may receive warnings like {{ic|/run/lvm/lvmetad.socket: connect failed: No such file or directory}} or {{ic|WARNING: failed to connect to lvmetad: No such file or directory. Falling back to internal scanning.}} This is because {{ic|/run}} is not available inside the chroot. These warnings will not prevent the system from booting, provided that everything has been done correctly, so you may continue with the installation.<br />
<br />
=== GRUB loads slowly ===<br />
<br />
GRUB can take a long time to load when disk space is low. Check if you have sufficient free disk space on your {{ic|/boot}} or {{ic|/}} partition when you are having problems.<br />
<br />
=== error: unknown filesystem ===<br />
GRUB may output {{ic|error: unknown filesystem}} and refuse to boot for a few reasons. If you are certain that all [[UUID]]s are correct and all filesystems are valid and supported, it may be because your [[#GUID_Partition_Table_.28GPT.29_specific_instructions|BIOS Boot Partition]] is located outside the first 2TB of the drive [https://bbs.archlinux.org/viewtopic.php?id=195948]. Use a partitioning tool of your choice to ensure this partition is located fully within the first 2TB, then reinstall and reconfigure GRUB.<br />
<br />
=== grub-reboot not resetting ===<br />
<br />
GRUB seems to be unable to write to root BTRFS partitions [https://bbs.archlinux.org/viewtopic.php?id=166131]. If you use grub-reboot to boot into another entry it will therefore be unable to update its on-disk environment. Either run grub-reboot from the other entry (for example when switching between various distributions) or consider a different file system. You can reset a "sticky" entry by executing {{ic|grub-editenv create}} and setting {{ic|GRUB_DEFAULT<nowiki>=</nowiki>0}} in your {{ic|/etc/default/grub}} (don't forget {{ic|grub-mkconfig}}).<br />
<br />
=== Old BTRFS prevents installation ===<br />
<br />
If a drive is formatted with BTRFS without creating a partition table (eg. /dev/sdx), then later has partition table written to, there are parts of the BTRFS format that persist. Most utilities and OS's do not see this, but GRUB will refuse to install, even with --force<br />
<br />
# grub-install: warning: Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet..<br />
# grub-install: error: filesystem `btrfs' doesn't support blocklists.<br />
<br />
You can zero the drive, but the easy solution that leaves your data alone is to erase the BTRFS superblock with {{ic|wipefs -o 0x10040 /dev/sdx}}<br />
<br />
== See also ==<br />
<br />
* Official GRUB Manual - https://www.gnu.org/software/grub/manual/grub.html<br />
* Ubuntu wiki page for GRUB - https://help.ubuntu.com/community/Grub2<br />
* GRUB wiki page describing steps to compile for UEFI systems - https://help.ubuntu.com/community/UEFIBooting<br />
* Wikipedia's page on [[Wikipedia:BIOS Boot partition|BIOS Boot partition]]<br />
* http://members.iinet.net/~herman546/p20/GRUB2%20Configuration%20File%20Commands.html - quite complete description of how to configure GRUB</div>Stbinanhttps://wiki.archlinux.org/index.php?title=GRUB&diff=416350GRUB2016-01-20T17:24:36Z<p>Stbinan: /* GNU/Linux menu entry */</p>
<hr />
<div>[[Category:Boot loaders]]<br />
[[ar:GRUB]]<br />
[[cs:GRUB]]<br />
[[de:GRUB]]<br />
[[el:GRUB]]<br />
[[es:GRUB]]<br />
[[fr:GRUB]]<br />
[[he:GRUB]]<br />
[[id:GRUB]]<br />
[[it:GRUB]]<br />
[[ja:GRUB]]<br />
[[nl:GRUB]]<br />
[[pt:GRUB]]<br />
[[ru:GRUB]]<br />
[[tr:GRUB2]]<br />
[[uk:GRUB]]<br />
[[zh-cn:GRUB]]<br />
[[zh-tw:GRUB]]<br />
{{Related articles start}}<br />
{{Related|Arch boot process}}<br />
{{Related|Boot loaders}}<br />
{{Related|Master Boot Record}}<br />
{{Related|GUID Partition Table}}<br />
{{Related|Unified Extensible Firmware Interface}}<br />
{{Related|GRUB Legacy}}<br />
{{Related|GRUB/EFI examples}}<br />
{{Related|GRUB/Tips and tricks}}<br />
{{Related articles end}}<br />
[https://www.gnu.org/software/grub/ GRUB] — not to be confused with [[GRUB Legacy]] — is the next generation of the GRand Unified Bootloader. GRUB is derived from [http://www.nongnu.org/pupa/ PUPA] which was a research project to develop the next generation of what is now GRUB Legacy. GRUB has been rewritten from scratch to clean up everything and provide modularity and portability [https://www.gnu.org/software/grub/grub-faq.html#q1].<br />
<br />
== Preface ==<br />
<br />
* A ''bootloader'' is the first software program that runs when a computer starts. It is responsible for loading and transferring control to the Linux kernel. The kernel, in turn, initializes the rest of the operating system.<br />
* The name ''GRUB'' officially refers to version ''2'' of the software, see [https://www.gnu.org/software/grub/]. If you are looking for the article on the legacy version, see [[GRUB Legacy]].<br />
* GRUB supports [[Btrfs]] as root (without a separate {{ic|/boot}} file system) compressed with either zlib or LZO<br />
** GRUB currently (Sep 2015) supports booting from [[Btrfs]] RAID 0/1/10, but ''not'' RAID 5/6. You may use [[mdadm]] for RAID 5/6, which is supported by GRUB.<br />
* GRUB does not support [[F2FS]] as root so you will need a separate {{ic|/boot}} with a supported file system.<br />
<br />
== BIOS systems ==<br />
<br />
=== GUID Partition Table (GPT) specific instructions ===<br />
<br />
On a BIOS/[[GPT]] configuration a [http://www.gnu.org/software/grub/manual/html_node/BIOS-installation.html BIOS boot partition] is required. GRUB embeds its {{ic|core.img}} into this partition.<br />
<br />
{{Note|<br />
* Before attempting this method keep in mind that not all systems will be able to support this partitioning scheme, read more on [[GUID Partition Table#BIOS systems|GUID partition tables]].<br />
* This additional partition is only needed on a GRUB, BIOS/GPT partitioning scheme. Previously, for a GRUB, BIOS/MBR partitioning scheme, GRUB used the Post-MBR gap for the embedding the {{ic|core.img}}). GRUB for GPT, however, does not use the Post-GPT gap to conform to GPT specifications that require 1_megabyte/2048_sector disk boundaries.<br />
* For [[UEFI]] systems this extra partition is not required as no embedding of boot sectors takes place in that case.<br />
}}<br />
<br />
Create a mebibyte partition ({{ic|1=+1M}} with {{ic|fdisk}} or {{ic|gdisk}}) on the disk with no file system and type BIOS boot (''BIOS boot'' in fdisk, {{ic|ef02}} in gdisk, {{ic|bios_grub}} in {{ic|parted}}). This partition can be in any position order but has to be on the first 2 TiB of the disk. This partition needs to be created before GRUB installation. When the partition is ready, install the bootloader as per the instructions below.<br />
<br />
The post-GPT gap can also be used as the BIOS boot partition though it will be out of GPT alignment specification. Since the partition will not be regularly accessed performance issues can be disregarded (though some disk utilities will display a warning about it). In {{ic|fdisk}} or {{ic|gdisk}} create a new partition starting at sector 34 and spanning to 2047 and set the type. To have the viewable partitions begin at the base consider adding this partition last.<br />
<br />
=== Master Boot Record (MBR) specific instructions ===<br />
<br />
Usually the post-[[MBR]] gap (after the 512 byte MBR region and before the start of the first partition) in many MBR (or 'msdos' disklabel) partitioned systems is 31 KiB when DOS compatibility cylinder alignment issues are satisfied in the partition table. However a post-MBR gap of about 1 to 2 MiB is recommended to provide sufficient room for embedding GRUB's {{ic|core.img}} ({{bug|24103}}). It is advisable to use a partitioning tool that supports 1 MiB partition alignment to obtain this space as well as to satisfy other non-512 byte sector issues (which are unrelated to embedding of {{ic|core.img}}).<br />
<br />
=== Installation ===<br />
<br />
[[Install]] the {{Pkg|grub}} package. It will replace {{AUR|grub-legacy}}, where already installed.<br />
<br />
{{Note|Simply installing the package will not update the {{ic|/boot/grub/i386-pc/core.img}} file and the GRUB modules in {{ic|/boot/grub/i386-pc}}. You need to update them manually using {{ic|grub-install}} as explained below.}}<br />
<br />
==== Install boot files ====<br />
<br />
There are 4 ways to install GRUB boot files in BIOS booting:<br />
<br />
* [[#Install to disk|Install to disk]] (recommended)<br />
* [[#Install to external USB stick|Install to external USB stick]] (for recovery)<br />
* [[#Install to partition or partitionless disk|Install to partition or partitionless disk]] (not recommended)<br />
* [[#Generate core.img alone|Generate core.img alone]] (safest method, but requires another BIOS bootloader like [[Syslinux]] to be installed to chainload {{ic|/boot/grub/i386-pc/core.img}})<br />
<br />
{{Note|See https://www.gnu.org/software/grub/manual/html_node/BIOS-installation.html for additional documentation.}}<br />
<br />
===== Install to disk =====<br />
<br />
{{Note|The method is specific to installing GRUB to a partitioned (MBR or GPT) disk, with GRUB files installed to {{ic|/boot/grub}} and its first stage code installed to the 440-byte MBR boot code region (not to be confused with MBR partition table). }}<br />
<br />
The following commands will:<br />
* Set up GRUB in the 440-byte Master Boot Record boot code region<br />
* Populate the {{ic|/boot/grub}} directory<br />
* Generate the {{ic|/boot/grub/i386-pc/core.img}} file<br />
* Embed it in the 31 KiB (minimum size - varies depending on partition alignment) post-MBR gap in case of MBR partitioned disk<br />
* In the case of a GPT partitioned disk it will embed it in the BIOS Boot Partition , denoted by {{ic|bios_grub}} flag in parted and EF02 type code in gdisk<br />
<br />
# grub-install --recheck --target=i386-pc /dev/sd''x''<br />
# grub-mkconfig -o /boot/grub/grub.cfg<br />
<br />
If you use [[LVM]] for your {{ic|/boot}}, you can install GRUB on multiple physical disks.<br />
<br />
===== Install to external USB stick =====<br />
<br />
Assume your USB stick's first partition is FAT32 and its partition is /dev/sdy1<br />
<br />
# mkdir -p /mnt/usb ; mount /dev/sdy1 /mnt/usb<br />
# grub-install --target=i386-pc --recheck --debug --boot-directory=/mnt/usb/boot /dev/sdy<br />
# grub-mkconfig -o /mnt/usb/boot/grub/grub.cfg<br />
<br />
# optional, backup config files of grub.cfg<br />
# mkdir -p /mnt/usb/etc/default<br />
# cp /etc/default/grub /mnt/usb/etc/default<br />
# cp -a /etc/grub.d /mnt/usb/etc<br />
<br />
# sync; umount /mnt/usb<br />
<br />
===== Install to partition or partitionless disk =====<br />
{{Warning|GRUB '''strongly discourages''' installation to a partition boot sector or a partitionless disk as GRUB Legacy or Syslinux does. This setup is prone to breakage, especially during updates, and is '''not supported''' by the Arch developers.}}<br />
<br />
To set up grub to a partition boot sector, to a partitionless disk (also called superfloppy) or to a floppy disk, run (using for example {{ic|/dev/sdaX}} as the {{ic|/boot}} partition):<br />
<br />
# chattr -i /boot/grub/i386-pc/core.img<br />
# grub-install --target=i386-pc --recheck --debug --force /dev/sdaX<br />
# chattr +i /boot/grub/i386-pc/core.img<br />
<br />
{{Note|<br />
* {{ic|/dev/sdaX}} used for example only.<br />
* {{ic|1=--target=i386-pc}} instructs {{ic|grub-install}} to install for BIOS systems only. It is recommended to always use this option to remove ambiguity in ''grub-install''.<br />
}}<br />
<br />
You need to use the {{ic|--force}} option to allow usage of blocklists and should not use {{ic|1=--grub-setup=/bin/true}} (which is similar to simply generating {{ic|core.img}}).<br />
<br />
{{ic|grub-install}} will give out warnings like which should give you the idea of what might go wrong with this approach:<br />
<br />
/sbin/grub-setup: warn: Attempting to install GRUB to a partitionless disk or to a partition. This is a BAD idea.<br />
/sbin/grub-setup: warn: Embedding is not possible. GRUB can only be installed in this setup by using blocklists.<br />
However, blocklists are UNRELIABLE and their use is discouraged.<br />
<br />
Without {{ic|--force}} you may get the below error and {{ic|grub-setup}} will not setup its boot code in the partition boot sector:<br />
<br />
/sbin/grub-setup: error: will not proceed with blocklists<br />
<br />
With {{ic|--force}} you should get:<br />
<br />
Installation finished. No error reported.<br />
<br />
The reason why {{ic|grub-setup}} does not by default allow this is because in case of partition or a partitionless disk is that GRUB relies on embedded blocklists in the partition bootsector to locate the {{ic|/boot/grub/i386-pc/core.img}} file and the prefix directory {{ic|/boot/grub}}. The sector locations of {{ic|core.img}} may change whenever the file system in the partition is being altered (files copied, deleted etc.). For more info, see https://bugzilla.redhat.com/show_bug.cgi?id=728742 and https://bugzilla.redhat.com/show_bug.cgi?id=730915.<br />
<br />
The workaround for this is to set the immutable flag on {{ic|/boot/grub/i386-pc/core.img}} (using {{ic|chattr}} command as mentioned above) so that the sector locations of the {{ic|core.img}} file in the disk is not altered. The immutable flag on {{ic|/boot/grub/i386-pc/core.img}} needs to be set only if GRUB is installed to a partition boot sector or a partitionless disk, not in case of installation to MBR or simple generation of {{ic|core.img}} without embedding any bootsector (mentioned above).<br />
<br />
Unfortunately, the {{ic|grub.cfg}} file that is created will not contain the proper UUID in order to boot, even if it reports no errors. see https://bbs.archlinux.org/viewtopic.php?pid=1294604#p1294604.<br />
In order to fix this issue the following commands:<br />
<br />
# mount /dev/sdxY /mnt #Your root partition.<br />
# mount /dev/sdxZ /mnt/boot #Your boot partition (if you have one).<br />
# arch-chroot /mnt<br />
# pacman -S linux<br />
# grub-mkconfig -o /boot/grub/grub.cfg<br />
<br />
===== Generate core.img alone =====<br />
<br />
To populate the {{ic|/boot/grub}} directory and generate a {{ic|/boot/grub/i386-pc/core.img}} file '''without''' embedding any GRUB bootsector code in the MBR, post-MBR region, or the partition bootsector, add {{ic|1=--grub-setup=/bin/true}} to {{ic|grub-install}}:<br />
<br />
# grub-install --target=i386-pc --grub-setup=/bin/true --recheck --debug /dev/sda<br />
<br />
{{Note|<br />
* {{ic|/dev/sda}} used for example only.<br />
* {{ic|1=--target=i386-pc}} instructs {{ic|grub-install}} to install for BIOS systems only. It is recommended to always use this option to remove ambiguity in grub-install.<br />
}}<br />
<br />
You can then chainload GRUB's {{ic|core.img}} from GRUB Legacy or syslinux as a Linux kernel or as a multiboot kernel (see also [[Syslinux#Chainloading]]).<br />
<br />
== UEFI systems ==<br />
<br />
{{Note|<br />
* It is recommended to read and understand the [[UEFI]], [[GPT]] and [[UEFI Bootloaders]] pages.<br />
* When installing to use UEFI it is important to start the install with your machine in UEFI mode. The Arch Linux install media must be UEFI bootable.<br />
}}<br />
<br />
=== Check if you have GPT and an ESP ===<br />
<br />
An EFI System Partition (ESP) is needed on every disc you want to boot using EFI. GPT is not strictly necessary, but it is highly recommended and is the only method currently supported in this article. If you are installing Arch Linux on an EFI-capable computer with an already-working operating system, like Windows 8 for example, it is very likely that you already have an ESP. To check for GPT and for an ESP, use {{ic|parted}} as root to print the partition table of the disk you want to boot from. (We are calling it {{ic|/dev/sda}}.)<br />
<br />
# parted /dev/sda print<br />
<br />
For GPT, you are looking for "Partition Table: GPT". For EFI, you are looking for a small (512 MiB or less) partition with a vfat file system and the ''boot'' flag enabled. On it, there should be a directory named "EFI". If these criteria are met, this is your ESP. Make note of the partition number. You will need to know which one it is, so you can mount it later on while installing GRUB to it.<br />
<br />
=== Create an ESP ===<br />
<br />
If you do not have an ESP, you will need to create one. See [[UEFI#EFI System Partition]]<br />
<br />
=== Installation ===<br />
<br />
{{Note|UEFI firmware are not implemented consistently by hardware manufacturers. The installation examples provided are intended to work on the widest range of UEFI systems possible. Those experiencing problems despite applying these methods are encouraged to share detailed information for their hardware-specific cases, especially where solving these problems. A [[GRUB/EFI examples]] article has been provided for such cases.}}<br />
<br />
This section assumes you are installing GRUB for x86_64 systems (x86_64-efi). For i686 systems, replace {{ic|x86_64-efi}} with {{ic|i386-efi}} where appropriate.<br />
<br />
Make sure you are in a [[bash]] shell. For example, when booting from the Arch ISO:<br />
<br />
# arch-chroot /mnt /bin/bash<br />
<br />
[[Install]] the packages {{Pkg|grub}} and {{Pkg|efibootmgr}}. ''GRUB'' is the bootloader, ''efibootmgr'' creates bootable {{ic|.efi}} stub entries used by the GRUB installation script.<br />
<br />
The following steps install the GRUB UEFI application to {{ic|'''$esp'''/EFI/grub}}, install its modules to {{ic|/boot/grub/x86_64-efi}}, and place the bootable {{ic|grubx64.efi}} stub in {{ic|'''$esp'''/EFI/grub}}.<br />
<br />
First, tell GRUB to use UEFI, set the boot directory and set the bootloader ID. Change {{ic|$esp}} to your efi partition (usually {{ic|/boot}}):<br />
<br />
# grub-install --target=x86_64-efi --efi-directory='''$esp''' --bootloader-id='''grub''' --recheck<br />
<br />
The {{ic|--bootloader-id}} is what appears in the boot options to identity the GRUB EFI boot option; make sure this is something you will recognize later. The install will create a directory of the same name under {{ic|$esp/EFI/}} where the EFI binary bootloader will be placed. <br />
<br />
After the above install finished the main GRUB directory is located at {{ic|/boot/grub/}}. <br />
<br />
Remember to [[#Generate the main configuration file]] after finalizing further setup dependant [[#Configuration]]. <br />
<br />
{{Note|<br />
* While some distributions require a {{ic|/boot/efi}} or {{ic|/boot/EFI}} directory, Arch does not.<br />
* {{ic|--efi-directory}} and {{ic|--bootloader-id}} are specific to GRUB UEFI. {{ic|--efi-directory}} specifies the mountpoint of the ESP. It replaces {{ic|--root-directory}}, which is deprecated. <br />
* You might note the absence of a <device_path> option (e.g.: {{ic|/dev/sda}}) in the {{ic|grub-install}} command. In fact any <device_path> provided will be ignored by the GRUB install script, as UEFI bootloaders do not use a MBR or partition boot sector at all.<br />
}}<br />
<br />
See [[#UEFI|UEFI troubleshooting]] in case of problems.<br />
<br />
=== Further reading ===<br />
<br />
Below is other relevant information regarding installing Arch via UEFI<br />
<br />
==== Alternative install method ====<br />
<br />
Usually, GRUB keeps all files, including configuration files, in {{ic|/boot}}, regardless of where the EFI System Partition is mounted.<br />
<br />
If you want to keep these files inside the EFI System Partition itself, add {{ic|--boot-directory&#61;$esp}} to the grub-install command:<br />
<br />
# grub-install --target=x86_64-efi --efi-directory=$esp --bootloader-id=grub --boot-directory=$esp --recheck --debug<br />
<br />
This puts all GRUB files in {{ic|$esp/grub}}, instead of in {{ic|/boot/grub}}. When using this method, make sure you have ''grub-mkconfig'' put the configuration file in the same place:<br />
<br />
# grub-mkconfig -o $esp/grub/grub.cfg<br />
<br />
Configuration is otherwise the same.<br />
<br />
==== UEFI firmware workaround ====<br />
<br />
Some UEFI firmware requires that the bootable {{ic|.efi}} stub have a specific name and be placed in a specific location: {{ic|$esp/EFI/boot/bootx64.efi}} (where {{ic|$esp}} is the UEFI partition mountpoint). Failure to do so in such instances will result in an unbootable installation. Fortunately, this will not cause any problems with other firmware that does not require this.<br />
<br />
To do so, first create the necessary directory, and then copy across the grub {{ic|.efi}} stub, renaming it in the process:<br />
<br />
# mkdir $esp/EFI/boot<br />
# cp $esp/EFI/grub_uefi/grubx64.efi $esp/EFI/boot/bootx64.efi<br />
<br />
==== Create a GRUB entry in the firmware boot manager ====<br />
{{ic|grub-install}} automatically tries to create a menu entry in the boot manager. If it does not, then see [[UEFI#efibootmgr]] for instructions to use {{ic|efibootmgr}} to create a menu entry. However, the problem is likely to be that you have not booted your CD/USB in UEFI mode, as in [[UEFI#Create UEFI bootable USB from ISO]].<br />
<br />
==== GRUB standalone ====<br />
<br />
This section assumes you are creating a standalone GRUB for x86_64 systems (x86_64-efi). For i686 systems, replace {{ic|x86_64-efi}} with {{ic|i386-efi}} where appropriate.<br />
<br />
It is possible to create a {{ic|grubx64_standalone.efi}} application which has all the modules embedded in a tar archive within the UEFI application, thus removing the need for having a separate directory populated with all of the GRUB UEFI modules and other related files. This is done using the {{ic|grub-mkstandalone}} command (included in {{Pkg|grub}}) as follows:<br />
<br />
# echo 'configfile ${cmdpath}/grub.cfg' > /tmp/grub.cfg<br />
# grub-mkstandalone -d /usr/lib/grub/x86_64-efi/ -O x86_64-efi --modules="part_gpt part_msdos" --fonts="unicode" --locales="en@quot" --themes="" -o "$esp/EFI/grub/grubx64_standalone.efi" "boot/grub/grub.cfg=/tmp/grub.cfg" -v<br />
<br />
Then copy the GRUB config file to {{ic|$esp/EFI/grub/grub.cfg}} and create a UEFI Boot Manager entry for {{ic|$esp/EFI/grub/grubx64_standalone.efi}} using [[UEFI#efibootmgr|efibootmgr]].<br />
<br />
{{Note|<br />
The option {{ic|1=--modules="part_gpt part_msdos"}} (with the quotes) is necessary for the {{ic|${cmdpath} }} feature to work properly.<br />
}}<br />
<br />
{{Warning|You may find that the {{ic|grub.cfg}} file is not loaded due to {{ic|${cmdpath} }} missing a slash (i.e. {{ic|(hd1,msdos2)EFI/Boot}} instead of {{ic|(hd1,msdos2)/EFI/Boot}}) and so you are dropped into a GRUB shell. If this happens determine what {{ic|${cmdpath} }} is set to ({{ic|echo ${cmdpath} }}) and then load the config file manually (e.g. {{ic|configfile (hd1,msdos2)/EFI/Boot/grub.cfg}}).}}<br />
<br />
==== Technical information ====<br />
<br />
The GRUB EFI file always expects its config file to be at {{ic|${prefix}/grub.cfg}}. However in the standalone GRUB EFI file, the {{ic|${prefix} }} is located inside a tar archive and embedded inside the standalone GRUB EFI file itself (inside the GRUB environment, it is denoted by {{ic|"(memdisk)"}}, without quotes). This tar archive contains all the files that would be stored normally at {{ic|/boot/grub}} in case of a normal GRUB EFI install.<br />
<br />
Due to this embedding of {{ic|/boot/grub}} contents inside the standalone image itself, it does not rely on actual (external) {{ic|/boot/grub}} for anything. Thus in case of standalone GRUB EFI file {{ic|1=${prefix}==(memdisk)/boot/grub}} and the standalone GRUB EFI file reads expects the config file to be at {{ic|1=${prefix}/grub.cfg==(memdisk)/boot/grub/grub.cfg}}.<br />
<br />
Hence to make sure the standalone GRUB EFI file reads the external {{ic|grub.cfg}} located in the same directory as the EFI file (inside the GRUB environment, it is denoted by {{ic|${cmdpath} }}), we create a simple {{ic|/tmp/grub.cfg}} which instructs GRUB to use {{ic|${cmdpath}/grub.cfg}} as its config ({{ic|configfile ${cmdpath}/grub.cfg}} command in {{ic|(memdisk)/boot/grub/grub.cfg}}). We then instruct grub-mkstandalone to copy this {{ic|/tmp/grub.cfg}} file to {{ic|${prefix}/grub.cfg}} (which is actually {{ic|(memdisk)/boot/grub/grub.cfg}}) using the option {{ic|1="boot/grub/grub.cfg=/tmp/grub.cfg"}}.<br />
<br />
This way, the standalone GRUB EFI file and actual {{ic|grub.cfg}} can be stored in any directory inside the EFI System Partition (as long as they are in the same directory), thus making them portable.<br />
<br />
== Generate the main configuration file ==<br />
<br />
After the installation, the main configuration file {{ic|grub.cfg}} needs to be generated. The generation process can be influenced by a variety of options in {{ic|/etc/default/grub}} and scripts in {{ic|/etc/grub.d/}}; see [[#Configuration]]. <br />
<br />
If you have not done additional configuration, the automatic generation will determine the root filesystem of the system to boot for the configuration file. For that to succeed it is important that the system is either booted or chrooted into. <br />
<br />
{{Note|Remember that {{ic|grub.cfg}} has to be re-generated after any change to {{ic|/etc/default/grub}} or files in {{ic|/etc/grub.d/}}.}}<br />
<br />
Use the ''grub-mkconfig'' tool to generate {{ic|grub.cfg}}:<br />
<br />
# grub-mkconfig -o /boot/grub/grub.cfg<br />
<br />
{{Note|<br />
* The default file path is {{ic|/boot/grub/grub.cfg}}, not {{ic|/boot/grub/i386-pc/grub.cfg}}. The {{Pkg|grub}} includes a sample {{ic|/boot/grub/grub.cfg}}; ensure your intended changes were written to this file.<br />
* If you are trying to run ''grub-mkconfig'' in a chroot or ''systemd-nspawn'' container, you might notice that it does not work, complaining that ''grub-probe'' cannot get the "canonical path of /dev/sdaX". In this case, try using ''arch-chroot'' as described in the [https://bbs.archlinux.org/viewtopic.php?pid&#61;1225067#p1225067 BBS post].<br />
}}<br />
<br />
By default the generation scripts automatically add menu entries for Arch Linux to any generated configuration. See [[#Dual-booting]] for configuration with other systems.<br />
<br />
== Configuration ==<br />
<br />
This section only covers editing the {{ic|/etc/default/grub}} configuration file. See [[GRUB/Tips and tricks]] for more information.<br />
<br />
Remember to always [[#Generate the main configuration file]] after making changes to {{ic|/etc/default/grub}}.<br />
<br />
=== Additional arguments ===<br />
<br />
To pass custom additional arguments to the Linux image, you can set the {{ic|GRUB_CMDLINE_LINUX}} + {{ic|GRUB_CMDLINE_LINUX_DEFAULT}} variables in {{ic|/etc/default/grub}}. The two are appended to each other and passed to kernel when generating regular boot entries. For the ''recovery'' boot entry, only {{ic|GRUB_CMDLINE_LINUX}} is used in the generation.<br />
<br />
It is not necessary to use both, but can be useful. For example, you could use {{ic|<nowiki>GRUB_CMDLINE_LINUX_DEFAULT="resume=/dev/sdaX</nowiki> quiet"}} where {{ic|sda'''X'''}} is your swap partition to enable resume after hibernation. This would generate a recovery boot entry without the resume and without ''quiet'' suppressing kernel messages during a boot from that menu entry. Though, the other (regular) menu entries would have them as options.<br />
<br />
By default ''grub-mkconfig'' determines the [[UUID]] of the root filesystem for the configuration. To disable this, uncomment {{ic|1=GRUB_DISABLE_LINUX_UUID=true}}. <br />
<br />
For generating the GRUB recovery entry you also have to comment out {{ic|<nowiki>#GRUB_DISABLE_RECOVERY=true</nowiki>}} in {{ic|/etc/default/grub}}.<br />
<br />
You can also use {{ic|<nowiki>GRUB_CMDLINE_LINUX="resume=UUID=uuid-of-swap-partition"</nowiki>}}<br />
<br />
See [[Kernel parameters]] for more info.<br />
<br />
=== Dual-booting ===<br />
<br />
{{Tip|To have ''grub-mkconfig'' search for other installed systems, [[install]] {{Pkg|os-prober}}.}}<br />
<br />
==== Automatically generating using /etc/grub.d/40_custom and grub-mkconfig ====<br />
<br />
The best way to add other entries is editing the {{ic|/etc/grub.d/40_custom}} or {{ic|/boot/grub/custom.cfg}}. The entries in this file will be automatically added when running {{ic|grub-mkconfig}}.<br />
After adding the new lines, run:<br />
{{bc|<nowiki># grub-mkconfig -o /boot/grub/grub.cfg</nowiki>}}<br />
or, for UEFI-GPT Mode (As per [[#Alternative install method]]):<br />
{{bc|<nowiki># grub-mkconfig -o /boot/efi/EFI/GRUB/grub.cfg</nowiki>}}<br />
to generate an updated {{ic|grub.cfg}}.<br />
<br />
For example, a typical {{ic|/etc/grub.d/40_custom}} file, could appear similar to the following one, created for [http://h10025.www1.hp.com/ewfrf/wc/product?cc=us&destPage=product&lc=en&product=5402703&tmp_docname= HP Pavilion 15-e056sl Notebook PC], originally with Microsoft Windows 8 preinstalled. Each {{ic|menuentry}} should maintain a structure similar to the following ones. Note that the UEFI partition {{ic|/dev/sda2}} within GRUB is called {{ic|hd0,gpt2}} and {{ic|ahci0,gpt2}} (see [[#Windows installed in UEFI-GPT Mode menu entry|here]] for more info).<br />
<br />
{{hc|/etc/grub.d/40_custom|<nowiki>#!/bin/sh<br />
exec tail -n +3 $0<br />
# This file provides an easy way to add custom menu entries.&nbsp; Simply type the<br />
# menu entries you want to add after this comment.&nbsp; Be careful not to change<br />
# the 'exec tail' line above.<br />
<br />
menuentry "HP / Microsoft Windows 8.1" {<br />
echo "Loading HP / Microsoft Windows 8.1..."<br />
insmod part_gpt<br />
insmod fat<br />
insmod search_fs_uuid<br />
insmod chain<br />
search --fs-uuid --no-floppy --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 763A-9CB6<br />
chainloader /EFI/Microsoft/Boot/bootmgfw.efi<br />
}<br />
<br />
menuentry "HP / Microsoft Control Center" {<br />
echo "Loading HP / Microsoft Control Center..."<br />
insmod part_gpt<br />
insmod fat<br />
insmod search_fs_uuid<br />
insmod chain<br />
search --fs-uuid --no-floppy --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 763A-9CB6<br />
chainloader /EFI/HP/boot/bootmgfw.efi<br />
}<br />
<br />
menuentry "System shutdown" {<br />
echo "System shutting down..."<br />
halt<br />
}<br />
<br />
menuentry "System restart" {<br />
echo "System rebooting..."<br />
reboot<br />
}</nowiki>}}<br />
<br />
===== GNU/Linux menu entry =====<br />
Assuming that the other distro is on partition {{ic|sda2}}:<br />
<br />
{{bc|<nowiki>menuentry "Other Linux" {<br />
set root=(hd0,2)<br />
linux /boot/vmlinuz (add other options here as required)<br />
initrd /boot/initrd.img (if the other kernel uses/needs one)<br />
}</nowiki>}}<br />
<br />
Alternatively let grub search for the right partition by ''UUID'' or ''label'':<br />
<br />
{{bc|<nowiki>menuentry "Other Linux" {<br />
# assuming that UUID is 763A-9CB6<br />
search --set=root --fs-uuid 763A-9CB6<br />
<br />
# search by label OTHER_LINUX (make sure that partition label is unambiguous)<br />
#search --set=root --label OTHER_LINUX<br />
<br />
linux /boot/vmlinuz (add other options here as required, for example: root=UUID=763A-9CB6)<br />
initrd /boot/initrd.img (if the other kernel uses/needs one)<br />
}</nowiki>}}<br />
<br />
For some os like Nix OS and GuixSD, because the kernel doesn't get patched and is in a special place named store, the entry will be a bit different, below it's an example for GuixSD:<br />
<br />
{{bc|<nowiki>menuentry "GNU with Linux-Libre 4.2.5 (alpha)" {<br />
search --set=root --fs-uuid YOUR_ROOT_PARTITION_UUID<br />
search --file --set /gnu/store/zbm09fk0wxkw2wyygnn4gcfxj8s31ajd-linux-libre-4.2.5/bzImage<br />
<br />
linux /gnu/store/zbm09fk0wxkw2wyygnn4gcfxj8s31ajd-linux-libre-4.2.5/bzImage --root=UUID=YOUR_ROOT_PARTITION_UUID --system=/gnu/store/a1brgzara5mw72jnmhqjx0j69ah8p5mp-system --load=/gnu/store/a1brgzara5mw72jnmhqjx0j69ah8p5mp-system/boot<br />
initrd /gnu/store/a1brgzara5mw72jnmhqjx0j69ah8p5mp-system/initrd<br />
}</nowiki>}}<br />
<br />
===== FreeBSD menu entry =====<br />
The following three methods require that FreeBSD is installed on a single partition with UFS(v2). Assuming the nested BSD partition table is on {{ic|sda4}}:<br />
<br />
====== Loading the kernel directly ======<br />
{{bc|1=<br />
menuentry 'FreeBSD' {<br />
insmod ufs2<br />
set root='hd0,gpt4,bsd1'<br />
## or 'hd0,msdos4,bsd1', if using an IBM-PC (MS-DOS) style partition table<br />
kfreebsd /boot/kernel/kernel<br />
kfreebsd_loadenv /boot/device.hints<br />
set kFreeBSD.vfs.root.mountfrom=ufs:/dev/ada0s4a<br />
set kFreeBSD.vfs.root.mountfrom.options=rw<br />
}<br />
}}<br />
<br />
====== Chainloading the embedded boot record ======<br />
{{bc|1=<br />
menuentry 'FreeBSD' {<br />
insmod ufs2<br />
set root='hd0,gpt4,bsd1'<br />
chainloader +1<br />
}<br />
}}<br />
<br />
====== Running the traditional BSD 2nd stage loader ======<br />
{{bc|1=<br />
menuentry 'FreeBSD' {<br />
insmod ufs2<br />
set root='(hd0,4)'<br />
kfreebsd /boot/loader<br />
}<br />
}}<br />
<br />
===== Windows XP menu entry=====<br />
This assumes that your Windows partition is {{ic|sda3}}. Remember you need to point set root and chainloader to the system reserve partition that windows made when it installed, not the actual partition windows is on. This example works if your system reserve partition is {{ic|sda3}}.<br />
<br />
{{bc|<nowiki># (2) Windows XP<br />
menuentry "Windows XP" {<br />
set root="(hd0,3)"<br />
chainloader +1<br />
}</nowiki>}}<br />
<br />
If the Windows bootloader is on an entirely different hard drive than GRUB, it may be necessary to trick Windows into believing that it is the first hard drive. This was possible with {{ic|drivemap}}. Assuming GRUB is on {{ic|hd0}} and Windows is on {{ic|hd2}}, you need to add the following after {{ic|set root}}:<br />
<br />
{{bc|drivemap -s hd0 hd2}}<br />
<br />
===== Windows installed in UEFI-GPT Mode menu entry =====<br />
<br />
{{Note|This menuentry will work only in UEFI boot mode and only if the Windows bitness matches the UEFI bitness. It '''WILL NOT WORK''' in BIOS installed GRUB. See [[Dual boot with Windows#Windows UEFI vs BIOS limitations]] and [[Dual boot with Windows#Bootloader UEFI vs BIOS limitations]] for more info.}}<br />
<br />
{{bc|<nowiki>if [ "${grub_platform}" == "efi" ]; then<br />
menuentry "Microsoft Windows Vista/7/8/8.1 UEFI-GPT" {<br />
insmod part_gpt<br />
insmod fat<br />
insmod search_fs_uuid<br />
insmod chain<br />
search --fs-uuid --set=root $hints_string $fs_uuid<br />
chainloader /EFI/Microsoft/Boot/bootmgfw.efi<br />
}<br />
fi</nowiki>}}<br />
<br />
where {{ic|$hints_string}} and {{ic|$fs_uuid}} are obtained with the following two commands. {{ic|$fs_uuid}}'s command:<br />
<br />
{{hc|1=# grub-probe --target=fs_uuid $esp/EFI/Microsoft/Boot/bootmgfw.efi|2=<br />
1ce5-7f28<br />
}}<br />
<br />
{{ic|$hints_string}}'s command:<br />
<br />
{{hc|1=# grub-probe --target=hints_string $esp/EFI/Microsoft/Boot/bootmgfw.efi|2=<br />
--hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1<br />
}}<br />
<br />
These two commands assume the ESP Windows uses is mounted at {{ic|$esp}}. There might be case differences in the path to Windows's EFI file, what with being Windows, and all.<br />
<br />
===== "Shutdown" menu entry =====<br />
<br />
{{bc|<nowiki>menuentry "System shutdown" {<br />
echo "System shutting down..."<br />
halt<br />
}</nowiki>}}<br />
<br />
===== "Restart" menu entry =====<br />
<br />
{{bc|<nowiki>menuentry "System restart" {<br />
echo "System rebooting..."<br />
reboot<br />
}</nowiki>}}<br />
<br />
===== Windows installed in BIOS-MBR mode =====<br />
<br />
{{Poor writing|This section does not fit into the others, should be slimmed down a bit.}}<br />
<br />
{{Note|GRUB supports booting {{ic|bootmgr}} directly and chainload of partition boot sector is no longer required to boot Windows in a BIOS-MBR setup.}}<br />
<br />
{{Warning|It is the '''system partition''' that has {{ic|/bootmgr}}, not your "real" Windows partition (usually C:). In {{ic|blkid}} output, the system partition is the one with {{ic|LABEL&#61;"SYSTEM RESERVED"}} or {{ic|LABEL&#61;"SYSTEM"}} and is only about 100 to 200 MB in size (much like the boot partition for Arch). See [[Wikipedia:System partition and boot partition]] for more info.}}<br />
<br />
Throughout this section, it is assumed your Windows partition is {{ic|/dev/sda1}}. A different partition will change every instance of hd0,msdos1. First, find the UUID of the NTFS file system of the Windows's SYSTEM PARTITION where the {{ic|bootmgr}} and its files reside. For example, if Windows {{ic|bootmgr}} exists at {{ic|/media/SYSTEM_RESERVED/bootmgr}}:<br />
<br />
For Windows Vista/7/8/8.1:<br />
<br />
# grub-probe --target=fs_uuid /media/SYSTEM_RESERVED/bootmgr<br />
69B235F6749E84CE<br />
<br />
# grub-probe --target=hints_string /media/SYSTEM_RESERVED/bootmgr<br />
--hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1<br />
<br />
{{Note|For Windows XP, replace {{ic|bootmgr}} with {{ic|NTLDR}} in the above commands. And note that there may not be a separate SYSTEM_RESERVED partition; just probe the file NTLDR on your Windows partition.}}<br />
<br />
Then, add the below code to {{ic|/etc/grub.d/40_custom}} or {{ic|/boot/grub/custom.cfg}} and regenerate {{ic|grub.cfg}} with {{ic|grub-mkconfig}} as explained above to boot Windows (XP, Vista, 7 or 8) installed in BIOS-MBR mode:<br />
<br />
{{Note|These menuentries will work only in Legacy BIOS boot mode. It WILL NOT WORK in uefi installed grub(2). See [[Dual boot with Windows#Windows UEFI vs BIOS limitations]] and [[Dual boot with Windows#Bootloader UEFI vs BIOS limitations]].}}<br />
<br />
For Windows Vista/7/8/8.1:<br />
<br />
if [ "${grub_platform}" == "pc" ]; then<br />
menuentry "Microsoft Windows Vista/7/8/8.1 BIOS-MBR" {<br />
insmod part_msdos<br />
insmod ntfs<br />
insmod search_fs_uuid<br />
insmod ntldr <br />
search --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 69B235F6749E84CE<br />
ntldr /bootmgr<br />
}<br />
fi<br />
<br />
For Windows XP:<br />
<br />
if [ "${grub_platform}" == "pc" ]; then<br />
menuentry "Microsoft Windows XP" {<br />
insmod part_msdos<br />
insmod ntfs<br />
insmod search_fs_uuid<br />
insmod ntldr <br />
search --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 69B235F6749E84CE<br />
ntldr /ntldr<br />
}<br />
fi<br />
<br />
{{Note|In some cases, mine I have installed GRUB before a clean Windows 8, you cannot boot Windows having an error with {{ic|\boot\bcd}} (error code {{ic|0xc000000f}}). You can fix it going to Windows Recovery Console (cmd from install disk) and executing:<br />
x:\> "bootrec.exe /fixboot" <br />
x:\> "bootrec.exe /RebuildBcd".<br />
Do '''not''' use {{ic|bootrec.exe /Fixmbr}} because it will wipe GRUB out.}}<br />
<br />
{{ic|/etc/grub.d/40_custom}} can be used as a template to create {{ic|/etc/grub.d/nn_custom}}. Where {{ic|nn}} defines the precendence, indicating the order the script is executed. The order scripts are executed determine the placement in the grub boot menu.<br />
<br />
{{Note|{{ic|nn}} should be greater than 06 to ensure necessary scripts are executed first.}}<br />
<br />
==== With Windows via EasyBCD and NeoGRUB ====<br />
<br />
{{Merge|NeoGRUB|New page has been created, so this section should be merged there.}}<br />
<br />
Since EasyBCD's NeoGRUB currently does not understand the GRUB menu format, chainload to it by replacing the contents of your {{ic|C:\NST\menu.lst}} file with lines similar to the following:<br />
<br />
default 0<br />
timeout 1<br />
<br />
title Chainload into GRUB v2<br />
root (hd0,7)<br />
kernel /boot/grub/i386-pc/core.img<br />
<br />
Finally, [[#Generate the main configuration file]].<br />
<br />
==== parttool for hide/unhide ====<br />
<br />
If you have a Windows 9x paradigm with hidden {{ic|C:\}} disks GRUB can hide/unhide it using {{ic|parttool}}. For example, to boot the third {{ic|C:\}} disk of three Windows 9x installations on the CLI enter the CLI and:<br />
parttool hd0,1 hidden+ boot-<br />
parttool hd0,2 hidden+ boot-<br />
parttool hd0,3 hidden- boot+<br />
set root=hd0,3<br />
chainloader +1<br />
boot<br />
<br />
=== LVM ===<br />
<br />
If you use [[LVM]] for your {{ic|/boot}}, make sure that the {{ic|lvm}} module is preloaded:<br />
<br />
{{hc|/etc/default/grub|2=<br />
GRUB_PRELOAD_MODULES="lvm"<br />
}}<br />
<br />
=== RAID ===<br />
<br />
GRUB provides convenient handling of RAID volumes. You need to add {{ic|insmod mdraid}} which allows you to address the volume natively. For example, {{ic|/dev/md0}} becomes:<br />
set root=(md/0)<br />
<br />
whereas a partitioned RAID volume (e.g. {{ic|/dev/md0p1}}) becomes:<br />
set root=(md/0,1)<br />
<br />
To install grub when using RAID1 as the {{ic|/boot}} partition (or using {{ic|/boot}} housed on a RAID1 root partition), on devices with GPT ef02/'BIOS boot partition', simply run ''grub-install'' on both of the drives, such as:<br />
# grub-install --target=i386-pc --recheck --debug /dev/sda<br />
# grub-install --target=i386-pc --recheck --debug /dev/sdb<br />
<br />
Where the RAID 1 array housing {{ic|/boot}} is housed on {{ic|/dev/sda}} and {{ic|/dev/sdb}}.<br />
<br />
=== Multiple entries ===<br />
<br />
For tips on managing multiple GRUB entries, for example when using both {{Pkg|linux}} and {{Pkg|linux-lts}} kernels, see [[GRUB/Tips and tricks#Multiple entries]].<br />
<br />
=== Encryption ===<br />
<br />
==== Root partition ====<br />
<br />
For an encrypted root filesystem, it is necessary to edit {{ic|/etc/default/grub}} with the parameters required to unlock the encrypted filesystem during boot. For example, if the [[mkinitcpio]] {{ic|encrypt}} hook is used, the {{ic|cryptdevice}} parameter must be added to {{ic|GRUB_CMDLINE_LINUX<nowiki>=</nowiki>""}} command. In the example below, the {{ic|sda2}} partition has been encrypted as {{ic|/dev/mapper/cryptroot}}:<br />
<br />
{{hc|/etc/default/grub|2=<br />
GRUB_CMDLINE_LINUX="cryptdevice=/dev/sda2:cryptroot"<br />
}}<br />
<br />
Once {{ic|/etc/default/grub}} has been amended, it will then be necessary to [[#Generate the main configuration file]].<br />
<br />
For further information about bootloader configuration for encrypted devices, see [[Dm-crypt/System configuration#Boot loader]].<br />
<br />
{{Tip|If you are upgrading from a working GRUB Legacy configuration, check {{ic|/boot/grub/menu.lst.pacsave}} for the correct device/label to add. Look for them after the text {{ic|kernel /vmlinuz-linux}}.}}<br />
<br />
==== Boot partition ====<br />
<br />
The GRUB [https://www.gnu.org/software/grub/manual/grub.html#Simple-configuration parameter] {{ic|GRUB_ENABLE_CRYPTODISK}} can be used to enable GRUB to ask for a password to open a [[LUKS]] blockdevice in order to read its configuration and load any [[initramfs]] and [[kernel]] from it. This option tries to solve the issue of having an [[Dm-crypt/Specialties#Securing_the_unencrypted_boot_partition|unencrypted boot partition]].<br />
<br />
The feature is enabled by adding: <br />
GRUB_ENABLE_CRYPTODISK=y<br />
to {{ic|/etc/default/grub}}. After this configuration a subsequent run of ''grub-mkconfig'' to [[#Generate the main configuration file]] is required while the encrypted {{ic|/boot}} is mounted. <br />
{{Note|{{ic|1=GRUB_ENABLE_CRYPTODISK=1}} [https://savannah.gnu.org/bugs/?41524 will not work] as opposed to the request shown in GRUB 2.02-beta2.}}<br />
<br />
Depending on the system's setup, note the following: <br />
<br />
* For the feature to work it is not required that {{ic|/boot}} is kept in a separate partition, it may also stay under the system's root {{ic|/}} directory tree.<br />
<br />
* Without further changes you will be prompted twice for a passhrase: the first for GRUB to unlock the {{ic|/boot}} mount point in early boot, the second to unlock the root filesystem itself as described in [[#Root partition]].{{Tip|See [[Dm-crypt/Device encryption#With a keyfile embedded in the initramfs]] for a workaround.}}<br />
<br />
* In order to perform system updates involving the {{ic|/boot}} mount point, it must be ensured that the encrypted {{ic|/boot}} is unlocked to be re-mounted by the initramfs and kernel during boot. With a separate {{ic|/boot}} partition, this may be accomplished by adding an entry to {{ic|/etc/crypttab}} with a keyfile. See [[Dm-crypt/System configuration#crypttab]].<br />
<br />
* If you use a special keymap, a default GRUB installation will not know it. This is relevant for how to enter the passphrase to unlock the LUKS blockdevice.<br />
<br />
* If you experience issues getting the prompt for a password to display (errors regarding cryptouuid, cryptodisk, or "device not found"), try reinstalling grub as below appending the following to the end of your installation command:<br />
<br />
grub-install --target=x86_64-efi --efi-directory=$esp --bootloader-id=grub --recheck '''--modules="part_gpt part_msdos"'''<br />
<br />
== Using the command shell ==<br />
<br />
Since the MBR is too small to store all GRUB modules, only the menu and a few basic commands reside there. The majority of GRUB functionality remains in modules in {{ic|/boot/grub}}, which are inserted as needed. In error conditions (e.g. if the partition layout changes) GRUB may fail to boot. When this happens, a command shell may appear.<br />
<br />
GRUB offers multiple shells/prompts. If there is a problem reading the menu but the bootloader is able to find the disk, you will likely be dropped to the "normal" shell:<br />
grub><br />
<br />
If there is a more serious problem (e.g. GRUB cannot find required files), you may instead be dropped to the "rescue" shell:<br />
grub rescue><br />
<br />
The rescue shell is a restricted subset of the normal shell, offering much less functionality. If dumped to the rescue shell, first try inserting the "normal" module, then starting the "normal" shell:<br />
grub rescue> set prefix=(hdX,Y)/boot/grub<br />
grub rescue> insmod (hdX,Y)/boot/grub/i386-pc/normal.mod<br />
rescue:grub> normal<br />
<br />
=== Pager support ===<br />
<br />
GRUB supports pager for reading commands that provide long output (like the {{ic|help}} command). This works only in normal shell mode and not in rescue mode. To enable pager, in GRUB command shell type:<br />
sh:grub> set pager=1<br />
<br />
=== Using the command shell environment to boot operating systems ===<br />
<br />
grub><br />
<br />
The GRUB's command shell environment can be used to boot operating systems.<br />
A common scenario may be to boot Windows / Linux stored on a drive/partition via '''chainloading'''.<br />
<br />
''Chainloading'' means to load another boot-loader from the current one, ie, chain-loading.<br />
<br />
The other bootloader may be embedded at the starting of the disk(MBR) or at the starting of a partition.<br />
<br />
==== Chainloading a partition ====<br />
<br />
set root=(hdX,Y)<br />
chainloader +1<br />
boot<br />
<br />
X=0,1,2...<br />
Y=1,2,3...<br />
<br />
For example to chainload Windows stored in the first partiton of the first hard disk,<br />
<br />
set root=(hd0,1)<br />
chainloader +1<br />
boot<br />
<br />
Similarly GRUB installed to a partition can be chainloaded.<br />
<br />
==== Chainloading a disk/drive ====<br />
<br />
set root=hdX<br />
chainloader +1<br />
boot<br />
<br />
==== Chainloading Windows/Linux installed in UEFI mode ====<br />
<br />
insmod ntfs<br />
set root=(hd0,gpt4)<br />
chainloader (${root})/EFI/Microsoft/Boot/bootmgfw.efi<br />
boot<br />
<br />
''insmod ntfs'' used for loading the ntfs file system module for loading Windows.<br />
(hd0,gpt4) or /dev/sda4 is my EFI System Partition (ESP).<br />
The entry in the ''chainloader'' line specifies the path of the .efi file to be chain-loaded.<br />
<br />
==== Normal loading ====<br />
<br />
See the examples in [[#Using the rescue console]]<br />
<br />
=== Using the rescue console ===<br />
<br />
See [[#Using the command shell]] first. If unable to activate the standard shell, one possible solution is to boot using a live CD or some other rescue disk to correct configuration errors and reinstall GRUB. However, such a boot disk is not always available (nor necessary); the rescue console is surprisingly robust.<br />
<br />
The available commands in GRUB rescue include {{ic|insmod}}, {{ic|ls}}, {{ic|set}}, and {{ic|unset}}. This example uses {{ic|set}} and {{ic|insmod}}. {{ic|set}} modifies variables and {{ic|insmod}} inserts new modules to add functionality.<br />
<br />
Before starting, the user must know the location of their {{ic|/boot}} partition (be it a separate partition, or a subdirectory under their root):<br />
<br />
grub rescue> set prefix=(hdX,Y)/boot/grub<br />
<br />
where X is the physical drive number and Y is the partition number.<br />
<br />
To expand console capabilities, insert the {{ic|linux}} module:<br />
grub rescue> insmod i386-pc/linux.mod<br />
<br />
{{Note|With a separate boot partition, omit {{ic|/boot}} from the path, (i.e. type {{ic|1=set prefix=(hdX,Y)/grub}}).}}<br />
<br />
This introduces the {{ic|linux}} and {{ic|initrd}} commands, which should be familiar.<br />
<br />
An example, booting Arch Linux:<br />
<br />
set root=(hd0,5)<br />
linux /boot/vmlinuz-linux root=/dev/sda5<br />
initrd /boot/initramfs-linux.img<br />
boot<br />
<br />
With a separate boot partition, again change the lines accordingly:<br />
<br />
set root=(hd0,5)<br />
linux /vmlinuz-linux root=/dev/sda6<br />
initrd /initramfs-linux.img<br />
boot<br />
<br />
{{Note|If you experienced {{ic|error: premature end of file /YOUR_KERNEL_NAME}} during execution of {{ic|linux}} command, you can try {{ic|linux16}} instead.}}<br />
<br />
After successfully booting the Arch Linux installation, users can correct {{ic|grub.cfg}} as needed and then reinstall GRUB.<br />
<br />
To reinstall GRUB and fix the problem completely, changing {{ic|/dev/sda}} if needed. See [[#Installation]] for details.<br />
<br />
== Troubleshooting ==<br />
<br />
=== Intel BIOS not booting GPT ===<br />
<br />
==== MBR ====<br />
<br />
Some Intel BIOS's require at least one bootable MBR partition to be present at boot, causing GPT-partitioned boot setups to be unbootable.<br />
<br />
This can be circumvented by using (for instance) fdisk to mark one of the GPT partitions (preferably the 1007 KiB partition you have created for GRUB already) bootable in the MBR. This can be achieved, using fdisk, by the following commands: Start fdisk against the disk you are installing, for instance {{ic|fdisk /dev/sda}}, then press {{ic|a}} and select the partition you wish to mark as bootable (probably #1) by pressing the corresponding number, finally press {{ic|w}} to write the changes to the MBR.<br />
<br />
{{Note|The bootable-marking must be done in {{ic|fdisk}} or similar, not in GParted or others, as they will not set the bootable flag in the MBR.}}<br />
<br />
With cfdisk, the steps are similar, just {{ic|cfdisk /dev/sda}}, choose bootable (at the left) in the desired hard disk, and quit saving.<br />
<br />
More information is available [http://www.rodsbooks.com/gdisk/bios.html here]<br />
<br />
==== EFI path ====<br />
<br />
Some UEFI firmwares require a bootable file at a known location before they will show UEFI NVRAM boot entries. If this is the case, {{ic|grub-install}} will claim {{ic|efibootmgr}} has added an entry to boot GRUB, however the entry will not show up in the VisualBIOS boot order selector. The solution is to place a file at one of the known locations. Assuming the EFI partition is at {{ic|/boot/efi/}} this will work:<br />
<br />
mkdir /boot/efi/EFI/boot<br />
cp /boot/efi/EFI/grub/grubx64.efi /boot/efi/EFI/boot/bootx64.efi<br />
<br />
This solution worked for an Intel DH87MC motherboard with firmware dated Jan 2014.<br />
<br />
=== Enable debug messages ===<br />
<br />
{{Note|This change is overwritten when [[#Generate the main configuration file]].}}<br />
<br />
Add:<br />
<br />
set pager=1<br />
set debug=all<br />
<br />
to {{ic|grub.cfg}}.<br />
<br />
=== "No suitable mode found" error ===<br />
<br />
If you get this error when booting any menuentry:<br />
<br />
error: no suitable mode found<br />
Booting however<br />
<br />
Then you need to initialize GRUB graphical terminal ({{ic|gfxterm}}) with proper video mode ({{ic|gfxmode}}) in GRUB. This video mode is passed by GRUB to the linux kernel via 'gfxpayload'. In case of UEFI systems, if the GRUB video mode is not initialized, no kernel boot messages will be shown in the terminal (atleast until KMS kicks in).<br />
<br />
Copy {{ic|/usr/share/grub/unicode.pf2}} to ${GRUB_PREFIX_DIR} ({{ic|/boot/grub/}} in case of BIOS and UEFI systems). If GRUB UEFI was installed with {{ic|1=--boot-directory=$esp/EFI}} set, then the directory is {{ic|$esp/EFI/grub/}}:<br />
<br />
# cp /usr/share/grub/unicode.pf2 ${GRUB_PREFIX_DIR}<br />
<br />
If {{ic|/usr/share/grub/unicode.pf2}} does not exist, install {{Pkg|bdf-unifont}}, create the {{ic|unifont.pf2}} file and then copy it to {{ic|${GRUB_PREFIX_DIR<nowiki>}</nowiki>}}:<br />
<br />
# grub-mkfont -o unicode.pf2 /usr/share/fonts/misc/unifont.bdf<br />
<br />
Then, in the {{ic|grub.cfg}} file, add the following lines to enable GRUB to pass the video mode correctly to the kernel, without of which you will only get a black screen (no output) but booting (actually) proceeds successfully without any system hang.<br />
<br />
BIOS systems:<br />
<br />
insmod vbe<br />
<br />
UEFI systems:<br />
<br />
insmod efi_gop<br />
insmod efi_uga<br />
<br />
After that add the following code (common to both BIOS and UEFI):<br />
<br />
insmod font<br />
<br />
if loadfont ${prefix}/fonts/unicode.pf2<br />
then<br />
insmod gfxterm<br />
set gfxmode=auto<br />
set gfxpayload=keep<br />
terminal_output gfxterm<br />
fi<br />
<br />
As you can see for gfxterm (graphical terminal) to function properly, {{ic|unicode.pf2}} font file should exist in {{ic|${GRUB_PREFIX_DIR<nowiki>}</nowiki>}}.<br />
<br />
=== msdos-style error message ===<br />
<br />
grub-setup: warn: This msdos-style partition label has no post-MBR gap; embedding will not be possible!<br />
grub-setup: warn: Embedding is not possible. GRUB can only be installed in this setup by using blocklists.<br />
However, blocklists are UNRELIABLE and its use is discouraged.<br />
grub-setup: error: If you really want blocklists, use --force.<br />
<br />
This error may occur when you try installing GRUB in a VMware container. Read more about it [https://bbs.archlinux.org/viewtopic.php?pid=581760#p581760 here]. It happens when the first partition starts just after the MBR (block 63), without the usual space of 1 MiB (2048 blocks) before the first partition. Read [[#Master Boot Record (MBR) specific instructions]]<br />
<br />
=== UEFI ===<br />
<br />
==== Common installation errors ====<br />
<br />
* If you have a problem when running grub-install with sysfs or procfs and it says you must run {{ic|modprobe efivars}}, try [[Unified Extensible Firmware Interface#Switch to efivarfs]].<br />
* Without {{ic|--target}} or {{ic|--directory}} option, grub-install cannot determine for which firmware to install. In such cases {{ic|grub-install}} will print {{ic|source_dir does not exist. Please specify --target or --directory}}.<br />
* If after running grub-install you are told your partition does not look like an EFI partition then the partition is most likely not {{ic|Fat32}}.<br />
<br />
==== Drop to rescue shell ====<br />
<br />
If GRUB loads but drops you into the rescue shell with no errors, it may be because of a missing or misplaced {{ic|grub.cfg}}. This will happen if GRUB UEFI was installed with {{ic|--boot-directory}} and {{ic|grub.cfg}} is missing OR if the partition number of the boot partition changed (which is hard-coded into the {{ic|grubx64.efi}} file).<br />
<br />
==== GRUB UEFI not loaded ====<br />
<br />
An example of a working EFI:<br />
<br />
{{hc|# efibootmgr -v|<br />
BootCurrent: 0000<br />
Timeout: 3 seconds<br />
BootOrder: 0000,0001,0002<br />
Boot0000* Grub HD(1,800,32000,23532fbb-1bfa-4e46-851a-b494bfe9478c)File(\efi\grub\grub.efi)<br />
Boot0001* Shell HD(1,800,32000,23532fbb-1bfa-4e46-851a-b494bfe9478c)File(\EfiShell.efi)<br />
Boot0002* Festplatte BIOS(2,0,00)P0: SAMSUNG HD204UI<br />
}}<br />
<br />
If the screen only goes black for a second and the next boot option is tried afterwards, according to [https://bbs.archlinux.org/viewtopic.php?pid=981560#p981560 this post], moving GRUB to the partition root can help. The boot option has to be deleted and recreated afterwards. The entry for GRUB should look like this then:<br />
<br />
Boot0000* Grub HD(1,800,32000,23532fbb-1bfa-4e46-851a-b494bfe9478c)File(\grub.efi)<br />
<br />
=== Invalid signature ===<br />
<br />
If trying to boot Windows results in an "invalid signature" error, e.g. after reconfiguring partitions or adding additional hard drives, (re)move GRUB's device configuration and let it reconfigure:<br />
<br />
# mv /boot/grub/device.map /boot/grub/device.map-old<br />
# grub-mkconfig -o /boot/grub/grub.cfg<br />
<br />
{{ic|grub-mkconfig}} should now mention all found boot options, including Windows. If it works, remove {{ic|/boot/grub/device.map-old}}.<br />
<br />
=== Boot freezes ===<br />
<br />
If booting gets stuck without any error message after GRUB loading the kernel and the initial ramdisk, try removing the {{ic|add_efi_memmap}} kernel parameter.<br />
<br />
=== Arch not found from other OS ===<br />
<br />
Some have reported that other distributions have trouble finding Arch Linux automatically with {{ic|os-prober}}. If this problem arises, it has been reported that detection can be improved with the presence of {{ic|/etc/lsb-release}}. This file and updating tool is available with the package {{Pkg|lsb-release}} in the [[official repositories]].<br />
<br />
=== Warning when installing in chroot ===<br />
<br />
When installing GRUB on a LVM system in a chroot environment (e.g. during system installation), you may receive warnings like {{ic|/run/lvm/lvmetad.socket: connect failed: No such file or directory}} or {{ic|WARNING: failed to connect to lvmetad: No such file or directory. Falling back to internal scanning.}} This is because {{ic|/run}} is not available inside the chroot. These warnings will not prevent the system from booting, provided that everything has been done correctly, so you may continue with the installation.<br />
<br />
=== GRUB loads slowly ===<br />
<br />
GRUB can take a long time to load when disk space is low. Check if you have sufficient free disk space on your {{ic|/boot}} or {{ic|/}} partition when you are having problems.<br />
<br />
=== error: unknown filesystem ===<br />
GRUB may output {{ic|error: unknown filesystem}} and refuse to boot for a few reasons. If you are certain that all [[UUID]]s are correct and all filesystems are valid and supported, it may be because your [[#GUID_Partition_Table_.28GPT.29_specific_instructions|BIOS Boot Partition]] is located outside the first 2TB of the drive [https://bbs.archlinux.org/viewtopic.php?id=195948]. Use a partitioning tool of your choice to ensure this partition is located fully within the first 2TB, then reinstall and reconfigure GRUB.<br />
<br />
=== grub-reboot not resetting ===<br />
<br />
GRUB seems to be unable to write to root BTRFS partitions [https://bbs.archlinux.org/viewtopic.php?id=166131]. If you use grub-reboot to boot into another entry it will therefore be unable to update its on-disk environment. Either run grub-reboot from the other entry (for example when switching between various distributions) or consider a different file system. You can reset a "sticky" entry by executing {{ic|grub-editenv create}} and setting {{ic|GRUB_DEFAULT<nowiki>=</nowiki>0}} in your {{ic|/etc/default/grub}} (don't forget {{ic|grub-mkconfig}}).<br />
<br />
=== Old BTRFS prevents installation ===<br />
<br />
If a drive is formatted with BTRFS without creating a partition table (eg. /dev/sdx), then later has partition table written to, there are parts of the BTRFS format that persist. Most utilities and OS's do not see this, but GRUB will refuse to install, even with --force<br />
<br />
# grub-install: warning: Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet..<br />
# grub-install: error: filesystem `btrfs' doesn't support blocklists.<br />
<br />
You can zero the drive, but the easy solution that leaves your data alone is to erase the BTRFS superblock with {{ic|wipefs -o 0x10040 /dev/sdx}}<br />
<br />
== See also ==<br />
<br />
* Official GRUB Manual - https://www.gnu.org/software/grub/manual/grub.html<br />
* Ubuntu wiki page for GRUB - https://help.ubuntu.com/community/Grub2<br />
* GRUB wiki page describing steps to compile for UEFI systems - https://help.ubuntu.com/community/UEFIBooting<br />
* Wikipedia's page on [[Wikipedia:BIOS Boot partition|BIOS Boot partition]]<br />
* http://members.iinet.net/~herman546/p20/GRUB2%20Configuration%20File%20Commands.html - quite complete description of how to configure GRUB</div>Stbinanhttps://wiki.archlinux.org/index.php?title=GRUB&diff=416348GRUB2016-01-20T17:15:04Z<p>Stbinan: /* GNU/Linux menu entry */ The editing was removed in Jan. 12. I add reason why this entry is different from those of other GNU/Linux and put it under GNU/Linux label</p>
<hr />
<div>[[Category:Boot loaders]]<br />
[[ar:GRUB]]<br />
[[cs:GRUB]]<br />
[[de:GRUB]]<br />
[[el:GRUB]]<br />
[[es:GRUB]]<br />
[[fr:GRUB]]<br />
[[he:GRUB]]<br />
[[id:GRUB]]<br />
[[it:GRUB]]<br />
[[ja:GRUB]]<br />
[[nl:GRUB]]<br />
[[pt:GRUB]]<br />
[[ru:GRUB]]<br />
[[tr:GRUB2]]<br />
[[uk:GRUB]]<br />
[[zh-cn:GRUB]]<br />
[[zh-tw:GRUB]]<br />
{{Related articles start}}<br />
{{Related|Arch boot process}}<br />
{{Related|Boot loaders}}<br />
{{Related|Master Boot Record}}<br />
{{Related|GUID Partition Table}}<br />
{{Related|Unified Extensible Firmware Interface}}<br />
{{Related|GRUB Legacy}}<br />
{{Related|GRUB/EFI examples}}<br />
{{Related|GRUB/Tips and tricks}}<br />
{{Related articles end}}<br />
[https://www.gnu.org/software/grub/ GRUB] — not to be confused with [[GRUB Legacy]] — is the next generation of the GRand Unified Bootloader. GRUB is derived from [http://www.nongnu.org/pupa/ PUPA] which was a research project to develop the next generation of what is now GRUB Legacy. GRUB has been rewritten from scratch to clean up everything and provide modularity and portability [https://www.gnu.org/software/grub/grub-faq.html#q1].<br />
<br />
== Preface ==<br />
<br />
* A ''bootloader'' is the first software program that runs when a computer starts. It is responsible for loading and transferring control to the Linux kernel. The kernel, in turn, initializes the rest of the operating system.<br />
* The name ''GRUB'' officially refers to version ''2'' of the software, see [https://www.gnu.org/software/grub/]. If you are looking for the article on the legacy version, see [[GRUB Legacy]].<br />
* GRUB supports [[Btrfs]] as root (without a separate {{ic|/boot}} file system) compressed with either zlib or LZO<br />
** GRUB currently (Sep 2015) supports booting from [[Btrfs]] RAID 0/1/10, but ''not'' RAID 5/6. You may use [[mdadm]] for RAID 5/6, which is supported by GRUB.<br />
* GRUB does not support [[F2FS]] as root so you will need a separate {{ic|/boot}} with a supported file system.<br />
<br />
== BIOS systems ==<br />
<br />
=== GUID Partition Table (GPT) specific instructions ===<br />
<br />
On a BIOS/[[GPT]] configuration a [http://www.gnu.org/software/grub/manual/html_node/BIOS-installation.html BIOS boot partition] is required. GRUB embeds its {{ic|core.img}} into this partition.<br />
<br />
{{Note|<br />
* Before attempting this method keep in mind that not all systems will be able to support this partitioning scheme, read more on [[GUID Partition Table#BIOS systems|GUID partition tables]].<br />
* This additional partition is only needed on a GRUB, BIOS/GPT partitioning scheme. Previously, for a GRUB, BIOS/MBR partitioning scheme, GRUB used the Post-MBR gap for the embedding the {{ic|core.img}}). GRUB for GPT, however, does not use the Post-GPT gap to conform to GPT specifications that require 1_megabyte/2048_sector disk boundaries.<br />
* For [[UEFI]] systems this extra partition is not required as no embedding of boot sectors takes place in that case.<br />
}}<br />
<br />
Create a mebibyte partition ({{ic|1=+1M}} with {{ic|fdisk}} or {{ic|gdisk}}) on the disk with no file system and type BIOS boot (''BIOS boot'' in fdisk, {{ic|ef02}} in gdisk, {{ic|bios_grub}} in {{ic|parted}}). This partition can be in any position order but has to be on the first 2 TiB of the disk. This partition needs to be created before GRUB installation. When the partition is ready, install the bootloader as per the instructions below.<br />
<br />
The post-GPT gap can also be used as the BIOS boot partition though it will be out of GPT alignment specification. Since the partition will not be regularly accessed performance issues can be disregarded (though some disk utilities will display a warning about it). In {{ic|fdisk}} or {{ic|gdisk}} create a new partition starting at sector 34 and spanning to 2047 and set the type. To have the viewable partitions begin at the base consider adding this partition last.<br />
<br />
=== Master Boot Record (MBR) specific instructions ===<br />
<br />
Usually the post-[[MBR]] gap (after the 512 byte MBR region and before the start of the first partition) in many MBR (or 'msdos' disklabel) partitioned systems is 31 KiB when DOS compatibility cylinder alignment issues are satisfied in the partition table. However a post-MBR gap of about 1 to 2 MiB is recommended to provide sufficient room for embedding GRUB's {{ic|core.img}} ({{bug|24103}}). It is advisable to use a partitioning tool that supports 1 MiB partition alignment to obtain this space as well as to satisfy other non-512 byte sector issues (which are unrelated to embedding of {{ic|core.img}}).<br />
<br />
=== Installation ===<br />
<br />
[[Install]] the {{Pkg|grub}} package. It will replace {{AUR|grub-legacy}}, where already installed.<br />
<br />
{{Note|Simply installing the package will not update the {{ic|/boot/grub/i386-pc/core.img}} file and the GRUB modules in {{ic|/boot/grub/i386-pc}}. You need to update them manually using {{ic|grub-install}} as explained below.}}<br />
<br />
==== Install boot files ====<br />
<br />
There are 4 ways to install GRUB boot files in BIOS booting:<br />
<br />
* [[#Install to disk|Install to disk]] (recommended)<br />
* [[#Install to external USB stick|Install to external USB stick]] (for recovery)<br />
* [[#Install to partition or partitionless disk|Install to partition or partitionless disk]] (not recommended)<br />
* [[#Generate core.img alone|Generate core.img alone]] (safest method, but requires another BIOS bootloader like [[Syslinux]] to be installed to chainload {{ic|/boot/grub/i386-pc/core.img}})<br />
<br />
{{Note|See https://www.gnu.org/software/grub/manual/html_node/BIOS-installation.html for additional documentation.}}<br />
<br />
===== Install to disk =====<br />
<br />
{{Note|The method is specific to installing GRUB to a partitioned (MBR or GPT) disk, with GRUB files installed to {{ic|/boot/grub}} and its first stage code installed to the 440-byte MBR boot code region (not to be confused with MBR partition table). }}<br />
<br />
The following commands will:<br />
* Set up GRUB in the 440-byte Master Boot Record boot code region<br />
* Populate the {{ic|/boot/grub}} directory<br />
* Generate the {{ic|/boot/grub/i386-pc/core.img}} file<br />
* Embed it in the 31 KiB (minimum size - varies depending on partition alignment) post-MBR gap in case of MBR partitioned disk<br />
* In the case of a GPT partitioned disk it will embed it in the BIOS Boot Partition , denoted by {{ic|bios_grub}} flag in parted and EF02 type code in gdisk<br />
<br />
# grub-install --recheck --target=i386-pc /dev/sd''x''<br />
# grub-mkconfig -o /boot/grub/grub.cfg<br />
<br />
If you use [[LVM]] for your {{ic|/boot}}, you can install GRUB on multiple physical disks.<br />
<br />
===== Install to external USB stick =====<br />
<br />
Assume your USB stick's first partition is FAT32 and its partition is /dev/sdy1<br />
<br />
# mkdir -p /mnt/usb ; mount /dev/sdy1 /mnt/usb<br />
# grub-install --target=i386-pc --recheck --debug --boot-directory=/mnt/usb/boot /dev/sdy<br />
# grub-mkconfig -o /mnt/usb/boot/grub/grub.cfg<br />
<br />
# optional, backup config files of grub.cfg<br />
# mkdir -p /mnt/usb/etc/default<br />
# cp /etc/default/grub /mnt/usb/etc/default<br />
# cp -a /etc/grub.d /mnt/usb/etc<br />
<br />
# sync; umount /mnt/usb<br />
<br />
===== Install to partition or partitionless disk =====<br />
{{Warning|GRUB '''strongly discourages''' installation to a partition boot sector or a partitionless disk as GRUB Legacy or Syslinux does. This setup is prone to breakage, especially during updates, and is '''not supported''' by the Arch developers.}}<br />
<br />
To set up grub to a partition boot sector, to a partitionless disk (also called superfloppy) or to a floppy disk, run (using for example {{ic|/dev/sdaX}} as the {{ic|/boot}} partition):<br />
<br />
# chattr -i /boot/grub/i386-pc/core.img<br />
# grub-install --target=i386-pc --recheck --debug --force /dev/sdaX<br />
# chattr +i /boot/grub/i386-pc/core.img<br />
<br />
{{Note|<br />
* {{ic|/dev/sdaX}} used for example only.<br />
* {{ic|1=--target=i386-pc}} instructs {{ic|grub-install}} to install for BIOS systems only. It is recommended to always use this option to remove ambiguity in ''grub-install''.<br />
}}<br />
<br />
You need to use the {{ic|--force}} option to allow usage of blocklists and should not use {{ic|1=--grub-setup=/bin/true}} (which is similar to simply generating {{ic|core.img}}).<br />
<br />
{{ic|grub-install}} will give out warnings like which should give you the idea of what might go wrong with this approach:<br />
<br />
/sbin/grub-setup: warn: Attempting to install GRUB to a partitionless disk or to a partition. This is a BAD idea.<br />
/sbin/grub-setup: warn: Embedding is not possible. GRUB can only be installed in this setup by using blocklists.<br />
However, blocklists are UNRELIABLE and their use is discouraged.<br />
<br />
Without {{ic|--force}} you may get the below error and {{ic|grub-setup}} will not setup its boot code in the partition boot sector:<br />
<br />
/sbin/grub-setup: error: will not proceed with blocklists<br />
<br />
With {{ic|--force}} you should get:<br />
<br />
Installation finished. No error reported.<br />
<br />
The reason why {{ic|grub-setup}} does not by default allow this is because in case of partition or a partitionless disk is that GRUB relies on embedded blocklists in the partition bootsector to locate the {{ic|/boot/grub/i386-pc/core.img}} file and the prefix directory {{ic|/boot/grub}}. The sector locations of {{ic|core.img}} may change whenever the file system in the partition is being altered (files copied, deleted etc.). For more info, see https://bugzilla.redhat.com/show_bug.cgi?id=728742 and https://bugzilla.redhat.com/show_bug.cgi?id=730915.<br />
<br />
The workaround for this is to set the immutable flag on {{ic|/boot/grub/i386-pc/core.img}} (using {{ic|chattr}} command as mentioned above) so that the sector locations of the {{ic|core.img}} file in the disk is not altered. The immutable flag on {{ic|/boot/grub/i386-pc/core.img}} needs to be set only if GRUB is installed to a partition boot sector or a partitionless disk, not in case of installation to MBR or simple generation of {{ic|core.img}} without embedding any bootsector (mentioned above).<br />
<br />
Unfortunately, the {{ic|grub.cfg}} file that is created will not contain the proper UUID in order to boot, even if it reports no errors. see https://bbs.archlinux.org/viewtopic.php?pid=1294604#p1294604.<br />
In order to fix this issue the following commands:<br />
<br />
# mount /dev/sdxY /mnt #Your root partition.<br />
# mount /dev/sdxZ /mnt/boot #Your boot partition (if you have one).<br />
# arch-chroot /mnt<br />
# pacman -S linux<br />
# grub-mkconfig -o /boot/grub/grub.cfg<br />
<br />
===== Generate core.img alone =====<br />
<br />
To populate the {{ic|/boot/grub}} directory and generate a {{ic|/boot/grub/i386-pc/core.img}} file '''without''' embedding any GRUB bootsector code in the MBR, post-MBR region, or the partition bootsector, add {{ic|1=--grub-setup=/bin/true}} to {{ic|grub-install}}:<br />
<br />
# grub-install --target=i386-pc --grub-setup=/bin/true --recheck --debug /dev/sda<br />
<br />
{{Note|<br />
* {{ic|/dev/sda}} used for example only.<br />
* {{ic|1=--target=i386-pc}} instructs {{ic|grub-install}} to install for BIOS systems only. It is recommended to always use this option to remove ambiguity in grub-install.<br />
}}<br />
<br />
You can then chainload GRUB's {{ic|core.img}} from GRUB Legacy or syslinux as a Linux kernel or as a multiboot kernel (see also [[Syslinux#Chainloading]]).<br />
<br />
== UEFI systems ==<br />
<br />
{{Note|<br />
* It is recommended to read and understand the [[UEFI]], [[GPT]] and [[UEFI Bootloaders]] pages.<br />
* When installing to use UEFI it is important to start the install with your machine in UEFI mode. The Arch Linux install media must be UEFI bootable.<br />
}}<br />
<br />
=== Check if you have GPT and an ESP ===<br />
<br />
An EFI System Partition (ESP) is needed on every disc you want to boot using EFI. GPT is not strictly necessary, but it is highly recommended and is the only method currently supported in this article. If you are installing Arch Linux on an EFI-capable computer with an already-working operating system, like Windows 8 for example, it is very likely that you already have an ESP. To check for GPT and for an ESP, use {{ic|parted}} as root to print the partition table of the disk you want to boot from. (We are calling it {{ic|/dev/sda}}.)<br />
<br />
# parted /dev/sda print<br />
<br />
For GPT, you are looking for "Partition Table: GPT". For EFI, you are looking for a small (512 MiB or less) partition with a vfat file system and the ''boot'' flag enabled. On it, there should be a directory named "EFI". If these criteria are met, this is your ESP. Make note of the partition number. You will need to know which one it is, so you can mount it later on while installing GRUB to it.<br />
<br />
=== Create an ESP ===<br />
<br />
If you do not have an ESP, you will need to create one. See [[UEFI#EFI System Partition]]<br />
<br />
=== Installation ===<br />
<br />
{{Note|UEFI firmware are not implemented consistently by hardware manufacturers. The installation examples provided are intended to work on the widest range of UEFI systems possible. Those experiencing problems despite applying these methods are encouraged to share detailed information for their hardware-specific cases, especially where solving these problems. A [[GRUB/EFI examples]] article has been provided for such cases.}}<br />
<br />
This section assumes you are installing GRUB for x86_64 systems (x86_64-efi). For i686 systems, replace {{ic|x86_64-efi}} with {{ic|i386-efi}} where appropriate.<br />
<br />
Make sure you are in a [[bash]] shell. For example, when booting from the Arch ISO:<br />
<br />
# arch-chroot /mnt /bin/bash<br />
<br />
[[Install]] the packages {{Pkg|grub}} and {{Pkg|efibootmgr}}. ''GRUB'' is the bootloader, ''efibootmgr'' creates bootable {{ic|.efi}} stub entries used by the GRUB installation script.<br />
<br />
The following steps install the GRUB UEFI application to {{ic|'''$esp'''/EFI/grub}}, install its modules to {{ic|/boot/grub/x86_64-efi}}, and place the bootable {{ic|grubx64.efi}} stub in {{ic|'''$esp'''/EFI/grub}}.<br />
<br />
First, tell GRUB to use UEFI, set the boot directory and set the bootloader ID. Change {{ic|$esp}} to your efi partition (usually {{ic|/boot}}):<br />
<br />
# grub-install --target=x86_64-efi --efi-directory='''$esp''' --bootloader-id='''grub''' --recheck<br />
<br />
The {{ic|--bootloader-id}} is what appears in the boot options to identity the GRUB EFI boot option; make sure this is something you will recognize later. The install will create a directory of the same name under {{ic|$esp/EFI/}} where the EFI binary bootloader will be placed. <br />
<br />
After the above install finished the main GRUB directory is located at {{ic|/boot/grub/}}. <br />
<br />
Remember to [[#Generate the main configuration file]] after finalizing further setup dependant [[#Configuration]]. <br />
<br />
{{Note|<br />
* While some distributions require a {{ic|/boot/efi}} or {{ic|/boot/EFI}} directory, Arch does not.<br />
* {{ic|--efi-directory}} and {{ic|--bootloader-id}} are specific to GRUB UEFI. {{ic|--efi-directory}} specifies the mountpoint of the ESP. It replaces {{ic|--root-directory}}, which is deprecated. <br />
* You might note the absence of a <device_path> option (e.g.: {{ic|/dev/sda}}) in the {{ic|grub-install}} command. In fact any <device_path> provided will be ignored by the GRUB install script, as UEFI bootloaders do not use a MBR or partition boot sector at all.<br />
}}<br />
<br />
See [[#UEFI|UEFI troubleshooting]] in case of problems.<br />
<br />
=== Further reading ===<br />
<br />
Below is other relevant information regarding installing Arch via UEFI<br />
<br />
==== Alternative install method ====<br />
<br />
Usually, GRUB keeps all files, including configuration files, in {{ic|/boot}}, regardless of where the EFI System Partition is mounted.<br />
<br />
If you want to keep these files inside the EFI System Partition itself, add {{ic|--boot-directory&#61;$esp}} to the grub-install command:<br />
<br />
# grub-install --target=x86_64-efi --efi-directory=$esp --bootloader-id=grub --boot-directory=$esp --recheck --debug<br />
<br />
This puts all GRUB files in {{ic|$esp/grub}}, instead of in {{ic|/boot/grub}}. When using this method, make sure you have ''grub-mkconfig'' put the configuration file in the same place:<br />
<br />
# grub-mkconfig -o $esp/grub/grub.cfg<br />
<br />
Configuration is otherwise the same.<br />
<br />
==== UEFI firmware workaround ====<br />
<br />
Some UEFI firmware requires that the bootable {{ic|.efi}} stub have a specific name and be placed in a specific location: {{ic|$esp/EFI/boot/bootx64.efi}} (where {{ic|$esp}} is the UEFI partition mountpoint). Failure to do so in such instances will result in an unbootable installation. Fortunately, this will not cause any problems with other firmware that does not require this.<br />
<br />
To do so, first create the necessary directory, and then copy across the grub {{ic|.efi}} stub, renaming it in the process:<br />
<br />
# mkdir $esp/EFI/boot<br />
# cp $esp/EFI/grub_uefi/grubx64.efi $esp/EFI/boot/bootx64.efi<br />
<br />
==== Create a GRUB entry in the firmware boot manager ====<br />
{{ic|grub-install}} automatically tries to create a menu entry in the boot manager. If it does not, then see [[UEFI#efibootmgr]] for instructions to use {{ic|efibootmgr}} to create a menu entry. However, the problem is likely to be that you have not booted your CD/USB in UEFI mode, as in [[UEFI#Create UEFI bootable USB from ISO]].<br />
<br />
==== GRUB standalone ====<br />
<br />
This section assumes you are creating a standalone GRUB for x86_64 systems (x86_64-efi). For i686 systems, replace {{ic|x86_64-efi}} with {{ic|i386-efi}} where appropriate.<br />
<br />
It is possible to create a {{ic|grubx64_standalone.efi}} application which has all the modules embedded in a tar archive within the UEFI application, thus removing the need for having a separate directory populated with all of the GRUB UEFI modules and other related files. This is done using the {{ic|grub-mkstandalone}} command (included in {{Pkg|grub}}) as follows:<br />
<br />
# echo 'configfile ${cmdpath}/grub.cfg' > /tmp/grub.cfg<br />
# grub-mkstandalone -d /usr/lib/grub/x86_64-efi/ -O x86_64-efi --modules="part_gpt part_msdos" --fonts="unicode" --locales="en@quot" --themes="" -o "$esp/EFI/grub/grubx64_standalone.efi" "boot/grub/grub.cfg=/tmp/grub.cfg" -v<br />
<br />
Then copy the GRUB config file to {{ic|$esp/EFI/grub/grub.cfg}} and create a UEFI Boot Manager entry for {{ic|$esp/EFI/grub/grubx64_standalone.efi}} using [[UEFI#efibootmgr|efibootmgr]].<br />
<br />
{{Note|<br />
The option {{ic|1=--modules="part_gpt part_msdos"}} (with the quotes) is necessary for the {{ic|${cmdpath} }} feature to work properly.<br />
}}<br />
<br />
{{Warning|You may find that the {{ic|grub.cfg}} file is not loaded due to {{ic|${cmdpath} }} missing a slash (i.e. {{ic|(hd1,msdos2)EFI/Boot}} instead of {{ic|(hd1,msdos2)/EFI/Boot}}) and so you are dropped into a GRUB shell. If this happens determine what {{ic|${cmdpath} }} is set to ({{ic|echo ${cmdpath} }}) and then load the config file manually (e.g. {{ic|configfile (hd1,msdos2)/EFI/Boot/grub.cfg}}).}}<br />
<br />
==== Technical information ====<br />
<br />
The GRUB EFI file always expects its config file to be at {{ic|${prefix}/grub.cfg}}. However in the standalone GRUB EFI file, the {{ic|${prefix} }} is located inside a tar archive and embedded inside the standalone GRUB EFI file itself (inside the GRUB environment, it is denoted by {{ic|"(memdisk)"}}, without quotes). This tar archive contains all the files that would be stored normally at {{ic|/boot/grub}} in case of a normal GRUB EFI install.<br />
<br />
Due to this embedding of {{ic|/boot/grub}} contents inside the standalone image itself, it does not rely on actual (external) {{ic|/boot/grub}} for anything. Thus in case of standalone GRUB EFI file {{ic|1=${prefix}==(memdisk)/boot/grub}} and the standalone GRUB EFI file reads expects the config file to be at {{ic|1=${prefix}/grub.cfg==(memdisk)/boot/grub/grub.cfg}}.<br />
<br />
Hence to make sure the standalone GRUB EFI file reads the external {{ic|grub.cfg}} located in the same directory as the EFI file (inside the GRUB environment, it is denoted by {{ic|${cmdpath} }}), we create a simple {{ic|/tmp/grub.cfg}} which instructs GRUB to use {{ic|${cmdpath}/grub.cfg}} as its config ({{ic|configfile ${cmdpath}/grub.cfg}} command in {{ic|(memdisk)/boot/grub/grub.cfg}}). We then instruct grub-mkstandalone to copy this {{ic|/tmp/grub.cfg}} file to {{ic|${prefix}/grub.cfg}} (which is actually {{ic|(memdisk)/boot/grub/grub.cfg}}) using the option {{ic|1="boot/grub/grub.cfg=/tmp/grub.cfg"}}.<br />
<br />
This way, the standalone GRUB EFI file and actual {{ic|grub.cfg}} can be stored in any directory inside the EFI System Partition (as long as they are in the same directory), thus making them portable.<br />
<br />
== Generate the main configuration file ==<br />
<br />
After the installation, the main configuration file {{ic|grub.cfg}} needs to be generated. The generation process can be influenced by a variety of options in {{ic|/etc/default/grub}} and scripts in {{ic|/etc/grub.d/}}; see [[#Configuration]]. <br />
<br />
If you have not done additional configuration, the automatic generation will determine the root filesystem of the system to boot for the configuration file. For that to succeed it is important that the system is either booted or chrooted into. <br />
<br />
{{Note|Remember that {{ic|grub.cfg}} has to be re-generated after any change to {{ic|/etc/default/grub}} or files in {{ic|/etc/grub.d/}}.}}<br />
<br />
Use the ''grub-mkconfig'' tool to generate {{ic|grub.cfg}}:<br />
<br />
# grub-mkconfig -o /boot/grub/grub.cfg<br />
<br />
{{Note|<br />
* The default file path is {{ic|/boot/grub/grub.cfg}}, not {{ic|/boot/grub/i386-pc/grub.cfg}}. The {{Pkg|grub}} includes a sample {{ic|/boot/grub/grub.cfg}}; ensure your intended changes were written to this file.<br />
* If you are trying to run ''grub-mkconfig'' in a chroot or ''systemd-nspawn'' container, you might notice that it does not work, complaining that ''grub-probe'' cannot get the "canonical path of /dev/sdaX". In this case, try using ''arch-chroot'' as described in the [https://bbs.archlinux.org/viewtopic.php?pid&#61;1225067#p1225067 BBS post].<br />
}}<br />
<br />
By default the generation scripts automatically add menu entries for Arch Linux to any generated configuration. See [[#Dual-booting]] for configuration with other systems.<br />
<br />
== Configuration ==<br />
<br />
This section only covers editing the {{ic|/etc/default/grub}} configuration file. See [[GRUB/Tips and tricks]] for more information.<br />
<br />
Remember to always [[#Generate the main configuration file]] after making changes to {{ic|/etc/default/grub}}.<br />
<br />
=== Additional arguments ===<br />
<br />
To pass custom additional arguments to the Linux image, you can set the {{ic|GRUB_CMDLINE_LINUX}} + {{ic|GRUB_CMDLINE_LINUX_DEFAULT}} variables in {{ic|/etc/default/grub}}. The two are appended to each other and passed to kernel when generating regular boot entries. For the ''recovery'' boot entry, only {{ic|GRUB_CMDLINE_LINUX}} is used in the generation.<br />
<br />
It is not necessary to use both, but can be useful. For example, you could use {{ic|<nowiki>GRUB_CMDLINE_LINUX_DEFAULT="resume=/dev/sdaX</nowiki> quiet"}} where {{ic|sda'''X'''}} is your swap partition to enable resume after hibernation. This would generate a recovery boot entry without the resume and without ''quiet'' suppressing kernel messages during a boot from that menu entry. Though, the other (regular) menu entries would have them as options.<br />
<br />
By default ''grub-mkconfig'' determines the [[UUID]] of the root filesystem for the configuration. To disable this, uncomment {{ic|1=GRUB_DISABLE_LINUX_UUID=true}}. <br />
<br />
For generating the GRUB recovery entry you also have to comment out {{ic|<nowiki>#GRUB_DISABLE_RECOVERY=true</nowiki>}} in {{ic|/etc/default/grub}}.<br />
<br />
You can also use {{ic|<nowiki>GRUB_CMDLINE_LINUX="resume=UUID=uuid-of-swap-partition"</nowiki>}}<br />
<br />
See [[Kernel parameters]] for more info.<br />
<br />
=== Dual-booting ===<br />
<br />
{{Tip|To have ''grub-mkconfig'' search for other installed systems, [[install]] {{Pkg|os-prober}}.}}<br />
<br />
==== Automatically generating using /etc/grub.d/40_custom and grub-mkconfig ====<br />
<br />
The best way to add other entries is editing the {{ic|/etc/grub.d/40_custom}} or {{ic|/boot/grub/custom.cfg}}. The entries in this file will be automatically added when running {{ic|grub-mkconfig}}.<br />
After adding the new lines, run:<br />
{{bc|<nowiki># grub-mkconfig -o /boot/grub/grub.cfg</nowiki>}}<br />
or, for UEFI-GPT Mode (As per [[#Alternative install method]]):<br />
{{bc|<nowiki># grub-mkconfig -o /boot/efi/EFI/GRUB/grub.cfg</nowiki>}}<br />
to generate an updated {{ic|grub.cfg}}.<br />
<br />
For example, a typical {{ic|/etc/grub.d/40_custom}} file, could appear similar to the following one, created for [http://h10025.www1.hp.com/ewfrf/wc/product?cc=us&destPage=product&lc=en&product=5402703&tmp_docname= HP Pavilion 15-e056sl Notebook PC], originally with Microsoft Windows 8 preinstalled. Each {{ic|menuentry}} should maintain a structure similar to the following ones. Note that the UEFI partition {{ic|/dev/sda2}} within GRUB is called {{ic|hd0,gpt2}} and {{ic|ahci0,gpt2}} (see [[#Windows installed in UEFI-GPT Mode menu entry|here]] for more info).<br />
<br />
{{hc|/etc/grub.d/40_custom|<nowiki>#!/bin/sh<br />
exec tail -n +3 $0<br />
# This file provides an easy way to add custom menu entries.&nbsp; Simply type the<br />
# menu entries you want to add after this comment.&nbsp; Be careful not to change<br />
# the 'exec tail' line above.<br />
<br />
menuentry "HP / Microsoft Windows 8.1" {<br />
echo "Loading HP / Microsoft Windows 8.1..."<br />
insmod part_gpt<br />
insmod fat<br />
insmod search_fs_uuid<br />
insmod chain<br />
search --fs-uuid --no-floppy --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 763A-9CB6<br />
chainloader /EFI/Microsoft/Boot/bootmgfw.efi<br />
}<br />
<br />
menuentry "HP / Microsoft Control Center" {<br />
echo "Loading HP / Microsoft Control Center..."<br />
insmod part_gpt<br />
insmod fat<br />
insmod search_fs_uuid<br />
insmod chain<br />
search --fs-uuid --no-floppy --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 763A-9CB6<br />
chainloader /EFI/HP/boot/bootmgfw.efi<br />
}<br />
<br />
menuentry "System shutdown" {<br />
echo "System shutting down..."<br />
halt<br />
}<br />
<br />
menuentry "System restart" {<br />
echo "System rebooting..."<br />
reboot<br />
}</nowiki>}}<br />
<br />
===== GNU/Linux menu entry =====<br />
Assuming that the other distro is on partition {{ic|sda2}}:<br />
<br />
{{bc|<nowiki>menuentry "Other Linux" {<br />
set root=(hd0,2)<br />
linux /boot/vmlinuz (add other options here as required)<br />
initrd /boot/initrd.img (if the other kernel uses/needs one)<br />
}</nowiki>}}<br />
<br />
Alternatively let grub search for the right partition by ''UUID'' or ''label'':<br />
<br />
{{bc|<nowiki>menuentry "Other Linux" {<br />
# assuming that UUID is 763A-9CB6<br />
search --set=root --fs-uuid 763A-9CB6<br />
<br />
# search by label OTHER_LINUX (make sure that partition label is unambiguous)<br />
#search --set=root --label OTHER_LINUX<br />
<br />
linux /boot/vmlinuz (add other options here as required, for example: root=UUID=763A-9CB6)<br />
initrd /boot/initrd.img (if the other kernel uses/needs one)<br />
}</nowiki>}}<br />
<br />
For some os like Nix OS and GuixSD, because the kernel doesn't get patched and is in a special place named store, the entry will be a bit different, below it's an example for GuixSD:<br />
<br />
{{bc|<nowiki>menuentry "GNU with Linux-Libre 4.2.5 (alpha)" {<br />
search --set=root --fs-uuid YOUR_ROOT_PARTITION_UUID<br />
search --file --set /gnu/store/zbm09fk0wxkw2wyygnn4gcfxj8s31ajd-linux-libre-4.2.5/bzImage<br />
<br />
linux /gnu/store/zbm09fk0wxkw2wyygnn4gcfxj8s31ajd-linux-libre-4.2.5/bzImage --root=gnu --system=/gnu/store/a1brgzara5mw72jnmhqjx0j69ah8p5mp-system --load=/gnu/store/a1brgzara5mw72jnmhqjx0j69ah8p5mp-system/boot<br />
initrd /gnu/store/a1brgzara5mw72jnmhqjx0j69ah8p5mp-system/initrd<br />
}</nowiki>}}<br />
<br />
===== FreeBSD menu entry =====<br />
The following three methods require that FreeBSD is installed on a single partition with UFS(v2). Assuming the nested BSD partition table is on {{ic|sda4}}:<br />
<br />
====== Loading the kernel directly ======<br />
{{bc|1=<br />
menuentry 'FreeBSD' {<br />
insmod ufs2<br />
set root='hd0,gpt4,bsd1'<br />
## or 'hd0,msdos4,bsd1', if using an IBM-PC (MS-DOS) style partition table<br />
kfreebsd /boot/kernel/kernel<br />
kfreebsd_loadenv /boot/device.hints<br />
set kFreeBSD.vfs.root.mountfrom=ufs:/dev/ada0s4a<br />
set kFreeBSD.vfs.root.mountfrom.options=rw<br />
}<br />
}}<br />
<br />
====== Chainloading the embedded boot record ======<br />
{{bc|1=<br />
menuentry 'FreeBSD' {<br />
insmod ufs2<br />
set root='hd0,gpt4,bsd1'<br />
chainloader +1<br />
}<br />
}}<br />
<br />
====== Running the traditional BSD 2nd stage loader ======<br />
{{bc|1=<br />
menuentry 'FreeBSD' {<br />
insmod ufs2<br />
set root='(hd0,4)'<br />
kfreebsd /boot/loader<br />
}<br />
}}<br />
<br />
===== Windows XP menu entry=====<br />
This assumes that your Windows partition is {{ic|sda3}}. Remember you need to point set root and chainloader to the system reserve partition that windows made when it installed, not the actual partition windows is on. This example works if your system reserve partition is {{ic|sda3}}.<br />
<br />
{{bc|<nowiki># (2) Windows XP<br />
menuentry "Windows XP" {<br />
set root="(hd0,3)"<br />
chainloader +1<br />
}</nowiki>}}<br />
<br />
If the Windows bootloader is on an entirely different hard drive than GRUB, it may be necessary to trick Windows into believing that it is the first hard drive. This was possible with {{ic|drivemap}}. Assuming GRUB is on {{ic|hd0}} and Windows is on {{ic|hd2}}, you need to add the following after {{ic|set root}}:<br />
<br />
{{bc|drivemap -s hd0 hd2}}<br />
<br />
===== Windows installed in UEFI-GPT Mode menu entry =====<br />
<br />
{{Note|This menuentry will work only in UEFI boot mode and only if the Windows bitness matches the UEFI bitness. It '''WILL NOT WORK''' in BIOS installed GRUB. See [[Dual boot with Windows#Windows UEFI vs BIOS limitations]] and [[Dual boot with Windows#Bootloader UEFI vs BIOS limitations]] for more info.}}<br />
<br />
{{bc|<nowiki>if [ "${grub_platform}" == "efi" ]; then<br />
menuentry "Microsoft Windows Vista/7/8/8.1 UEFI-GPT" {<br />
insmod part_gpt<br />
insmod fat<br />
insmod search_fs_uuid<br />
insmod chain<br />
search --fs-uuid --set=root $hints_string $fs_uuid<br />
chainloader /EFI/Microsoft/Boot/bootmgfw.efi<br />
}<br />
fi</nowiki>}}<br />
<br />
where {{ic|$hints_string}} and {{ic|$fs_uuid}} are obtained with the following two commands. {{ic|$fs_uuid}}'s command:<br />
<br />
{{hc|1=# grub-probe --target=fs_uuid $esp/EFI/Microsoft/Boot/bootmgfw.efi|2=<br />
1ce5-7f28<br />
}}<br />
<br />
{{ic|$hints_string}}'s command:<br />
<br />
{{hc|1=# grub-probe --target=hints_string $esp/EFI/Microsoft/Boot/bootmgfw.efi|2=<br />
--hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1<br />
}}<br />
<br />
These two commands assume the ESP Windows uses is mounted at {{ic|$esp}}. There might be case differences in the path to Windows's EFI file, what with being Windows, and all.<br />
<br />
===== "Shutdown" menu entry =====<br />
<br />
{{bc|<nowiki>menuentry "System shutdown" {<br />
echo "System shutting down..."<br />
halt<br />
}</nowiki>}}<br />
<br />
===== "Restart" menu entry =====<br />
<br />
{{bc|<nowiki>menuentry "System restart" {<br />
echo "System rebooting..."<br />
reboot<br />
}</nowiki>}}<br />
<br />
===== Windows installed in BIOS-MBR mode =====<br />
<br />
{{Poor writing|This section does not fit into the others, should be slimmed down a bit.}}<br />
<br />
{{Note|GRUB supports booting {{ic|bootmgr}} directly and chainload of partition boot sector is no longer required to boot Windows in a BIOS-MBR setup.}}<br />
<br />
{{Warning|It is the '''system partition''' that has {{ic|/bootmgr}}, not your "real" Windows partition (usually C:). In {{ic|blkid}} output, the system partition is the one with {{ic|LABEL&#61;"SYSTEM RESERVED"}} or {{ic|LABEL&#61;"SYSTEM"}} and is only about 100 to 200 MB in size (much like the boot partition for Arch). See [[Wikipedia:System partition and boot partition]] for more info.}}<br />
<br />
Throughout this section, it is assumed your Windows partition is {{ic|/dev/sda1}}. A different partition will change every instance of hd0,msdos1. First, find the UUID of the NTFS file system of the Windows's SYSTEM PARTITION where the {{ic|bootmgr}} and its files reside. For example, if Windows {{ic|bootmgr}} exists at {{ic|/media/SYSTEM_RESERVED/bootmgr}}:<br />
<br />
For Windows Vista/7/8/8.1:<br />
<br />
# grub-probe --target=fs_uuid /media/SYSTEM_RESERVED/bootmgr<br />
69B235F6749E84CE<br />
<br />
# grub-probe --target=hints_string /media/SYSTEM_RESERVED/bootmgr<br />
--hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1<br />
<br />
{{Note|For Windows XP, replace {{ic|bootmgr}} with {{ic|NTLDR}} in the above commands. And note that there may not be a separate SYSTEM_RESERVED partition; just probe the file NTLDR on your Windows partition.}}<br />
<br />
Then, add the below code to {{ic|/etc/grub.d/40_custom}} or {{ic|/boot/grub/custom.cfg}} and regenerate {{ic|grub.cfg}} with {{ic|grub-mkconfig}} as explained above to boot Windows (XP, Vista, 7 or 8) installed in BIOS-MBR mode:<br />
<br />
{{Note|These menuentries will work only in Legacy BIOS boot mode. It WILL NOT WORK in uefi installed grub(2). See [[Dual boot with Windows#Windows UEFI vs BIOS limitations]] and [[Dual boot with Windows#Bootloader UEFI vs BIOS limitations]].}}<br />
<br />
For Windows Vista/7/8/8.1:<br />
<br />
if [ "${grub_platform}" == "pc" ]; then<br />
menuentry "Microsoft Windows Vista/7/8/8.1 BIOS-MBR" {<br />
insmod part_msdos<br />
insmod ntfs<br />
insmod search_fs_uuid<br />
insmod ntldr <br />
search --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 69B235F6749E84CE<br />
ntldr /bootmgr<br />
}<br />
fi<br />
<br />
For Windows XP:<br />
<br />
if [ "${grub_platform}" == "pc" ]; then<br />
menuentry "Microsoft Windows XP" {<br />
insmod part_msdos<br />
insmod ntfs<br />
insmod search_fs_uuid<br />
insmod ntldr <br />
search --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 69B235F6749E84CE<br />
ntldr /ntldr<br />
}<br />
fi<br />
<br />
{{Note|In some cases, mine I have installed GRUB before a clean Windows 8, you cannot boot Windows having an error with {{ic|\boot\bcd}} (error code {{ic|0xc000000f}}). You can fix it going to Windows Recovery Console (cmd from install disk) and executing:<br />
x:\> "bootrec.exe /fixboot" <br />
x:\> "bootrec.exe /RebuildBcd".<br />
Do '''not''' use {{ic|bootrec.exe /Fixmbr}} because it will wipe GRUB out.}}<br />
<br />
{{ic|/etc/grub.d/40_custom}} can be used as a template to create {{ic|/etc/grub.d/nn_custom}}. Where {{ic|nn}} defines the precendence, indicating the order the script is executed. The order scripts are executed determine the placement in the grub boot menu.<br />
<br />
{{Note|{{ic|nn}} should be greater than 06 to ensure necessary scripts are executed first.}}<br />
<br />
==== With Windows via EasyBCD and NeoGRUB ====<br />
<br />
{{Merge|NeoGRUB|New page has been created, so this section should be merged there.}}<br />
<br />
Since EasyBCD's NeoGRUB currently does not understand the GRUB menu format, chainload to it by replacing the contents of your {{ic|C:\NST\menu.lst}} file with lines similar to the following:<br />
<br />
default 0<br />
timeout 1<br />
<br />
title Chainload into GRUB v2<br />
root (hd0,7)<br />
kernel /boot/grub/i386-pc/core.img<br />
<br />
Finally, [[#Generate the main configuration file]].<br />
<br />
==== parttool for hide/unhide ====<br />
<br />
If you have a Windows 9x paradigm with hidden {{ic|C:\}} disks GRUB can hide/unhide it using {{ic|parttool}}. For example, to boot the third {{ic|C:\}} disk of three Windows 9x installations on the CLI enter the CLI and:<br />
parttool hd0,1 hidden+ boot-<br />
parttool hd0,2 hidden+ boot-<br />
parttool hd0,3 hidden- boot+<br />
set root=hd0,3<br />
chainloader +1<br />
boot<br />
<br />
=== LVM ===<br />
<br />
If you use [[LVM]] for your {{ic|/boot}}, make sure that the {{ic|lvm}} module is preloaded:<br />
<br />
{{hc|/etc/default/grub|2=<br />
GRUB_PRELOAD_MODULES="lvm"<br />
}}<br />
<br />
=== RAID ===<br />
<br />
GRUB provides convenient handling of RAID volumes. You need to add {{ic|insmod mdraid}} which allows you to address the volume natively. For example, {{ic|/dev/md0}} becomes:<br />
set root=(md/0)<br />
<br />
whereas a partitioned RAID volume (e.g. {{ic|/dev/md0p1}}) becomes:<br />
set root=(md/0,1)<br />
<br />
To install grub when using RAID1 as the {{ic|/boot}} partition (or using {{ic|/boot}} housed on a RAID1 root partition), on devices with GPT ef02/'BIOS boot partition', simply run ''grub-install'' on both of the drives, such as:<br />
# grub-install --target=i386-pc --recheck --debug /dev/sda<br />
# grub-install --target=i386-pc --recheck --debug /dev/sdb<br />
<br />
Where the RAID 1 array housing {{ic|/boot}} is housed on {{ic|/dev/sda}} and {{ic|/dev/sdb}}.<br />
<br />
=== Multiple entries ===<br />
<br />
For tips on managing multiple GRUB entries, for example when using both {{Pkg|linux}} and {{Pkg|linux-lts}} kernels, see [[GRUB/Tips and tricks#Multiple entries]].<br />
<br />
=== Encryption ===<br />
<br />
==== Root partition ====<br />
<br />
For an encrypted root filesystem, it is necessary to edit {{ic|/etc/default/grub}} with the parameters required to unlock the encrypted filesystem during boot. For example, if the [[mkinitcpio]] {{ic|encrypt}} hook is used, the {{ic|cryptdevice}} parameter must be added to {{ic|GRUB_CMDLINE_LINUX<nowiki>=</nowiki>""}} command. In the example below, the {{ic|sda2}} partition has been encrypted as {{ic|/dev/mapper/cryptroot}}:<br />
<br />
{{hc|/etc/default/grub|2=<br />
GRUB_CMDLINE_LINUX="cryptdevice=/dev/sda2:cryptroot"<br />
}}<br />
<br />
Once {{ic|/etc/default/grub}} has been amended, it will then be necessary to [[#Generate the main configuration file]].<br />
<br />
For further information about bootloader configuration for encrypted devices, see [[Dm-crypt/System configuration#Boot loader]].<br />
<br />
{{Tip|If you are upgrading from a working GRUB Legacy configuration, check {{ic|/boot/grub/menu.lst.pacsave}} for the correct device/label to add. Look for them after the text {{ic|kernel /vmlinuz-linux}}.}}<br />
<br />
==== Boot partition ====<br />
<br />
The GRUB [https://www.gnu.org/software/grub/manual/grub.html#Simple-configuration parameter] {{ic|GRUB_ENABLE_CRYPTODISK}} can be used to enable GRUB to ask for a password to open a [[LUKS]] blockdevice in order to read its configuration and load any [[initramfs]] and [[kernel]] from it. This option tries to solve the issue of having an [[Dm-crypt/Specialties#Securing_the_unencrypted_boot_partition|unencrypted boot partition]].<br />
<br />
The feature is enabled by adding: <br />
GRUB_ENABLE_CRYPTODISK=y<br />
to {{ic|/etc/default/grub}}. After this configuration a subsequent run of ''grub-mkconfig'' to [[#Generate the main configuration file]] is required while the encrypted {{ic|/boot}} is mounted. <br />
{{Note|{{ic|1=GRUB_ENABLE_CRYPTODISK=1}} [https://savannah.gnu.org/bugs/?41524 will not work] as opposed to the request shown in GRUB 2.02-beta2.}}<br />
<br />
Depending on the system's setup, note the following: <br />
<br />
* For the feature to work it is not required that {{ic|/boot}} is kept in a separate partition, it may also stay under the system's root {{ic|/}} directory tree.<br />
<br />
* Without further changes you will be prompted twice for a passhrase: the first for GRUB to unlock the {{ic|/boot}} mount point in early boot, the second to unlock the root filesystem itself as described in [[#Root partition]].{{Tip|See [[Dm-crypt/Device encryption#With a keyfile embedded in the initramfs]] for a workaround.}}<br />
<br />
* In order to perform system updates involving the {{ic|/boot}} mount point, it must be ensured that the encrypted {{ic|/boot}} is unlocked to be re-mounted by the initramfs and kernel during boot. With a separate {{ic|/boot}} partition, this may be accomplished by adding an entry to {{ic|/etc/crypttab}} with a keyfile. See [[Dm-crypt/System configuration#crypttab]].<br />
<br />
* If you use a special keymap, a default GRUB installation will not know it. This is relevant for how to enter the passphrase to unlock the LUKS blockdevice.<br />
<br />
* If you experience issues getting the prompt for a password to display (errors regarding cryptouuid, cryptodisk, or "device not found"), try reinstalling grub as below appending the following to the end of your installation command:<br />
<br />
grub-install --target=x86_64-efi --efi-directory=$esp --bootloader-id=grub --recheck '''--modules="part_gpt part_msdos"'''<br />
<br />
== Using the command shell ==<br />
<br />
Since the MBR is too small to store all GRUB modules, only the menu and a few basic commands reside there. The majority of GRUB functionality remains in modules in {{ic|/boot/grub}}, which are inserted as needed. In error conditions (e.g. if the partition layout changes) GRUB may fail to boot. When this happens, a command shell may appear.<br />
<br />
GRUB offers multiple shells/prompts. If there is a problem reading the menu but the bootloader is able to find the disk, you will likely be dropped to the "normal" shell:<br />
grub><br />
<br />
If there is a more serious problem (e.g. GRUB cannot find required files), you may instead be dropped to the "rescue" shell:<br />
grub rescue><br />
<br />
The rescue shell is a restricted subset of the normal shell, offering much less functionality. If dumped to the rescue shell, first try inserting the "normal" module, then starting the "normal" shell:<br />
grub rescue> set prefix=(hdX,Y)/boot/grub<br />
grub rescue> insmod (hdX,Y)/boot/grub/i386-pc/normal.mod<br />
rescue:grub> normal<br />
<br />
=== Pager support ===<br />
<br />
GRUB supports pager for reading commands that provide long output (like the {{ic|help}} command). This works only in normal shell mode and not in rescue mode. To enable pager, in GRUB command shell type:<br />
sh:grub> set pager=1<br />
<br />
=== Using the command shell environment to boot operating systems ===<br />
<br />
grub><br />
<br />
The GRUB's command shell environment can be used to boot operating systems.<br />
A common scenario may be to boot Windows / Linux stored on a drive/partition via '''chainloading'''.<br />
<br />
''Chainloading'' means to load another boot-loader from the current one, ie, chain-loading.<br />
<br />
The other bootloader may be embedded at the starting of the disk(MBR) or at the starting of a partition.<br />
<br />
==== Chainloading a partition ====<br />
<br />
set root=(hdX,Y)<br />
chainloader +1<br />
boot<br />
<br />
X=0,1,2...<br />
Y=1,2,3...<br />
<br />
For example to chainload Windows stored in the first partiton of the first hard disk,<br />
<br />
set root=(hd0,1)<br />
chainloader +1<br />
boot<br />
<br />
Similarly GRUB installed to a partition can be chainloaded.<br />
<br />
==== Chainloading a disk/drive ====<br />
<br />
set root=hdX<br />
chainloader +1<br />
boot<br />
<br />
==== Chainloading Windows/Linux installed in UEFI mode ====<br />
<br />
insmod ntfs<br />
set root=(hd0,gpt4)<br />
chainloader (${root})/EFI/Microsoft/Boot/bootmgfw.efi<br />
boot<br />
<br />
''insmod ntfs'' used for loading the ntfs file system module for loading Windows.<br />
(hd0,gpt4) or /dev/sda4 is my EFI System Partition (ESP).<br />
The entry in the ''chainloader'' line specifies the path of the .efi file to be chain-loaded.<br />
<br />
==== Normal loading ====<br />
<br />
See the examples in [[#Using the rescue console]]<br />
<br />
=== Using the rescue console ===<br />
<br />
See [[#Using the command shell]] first. If unable to activate the standard shell, one possible solution is to boot using a live CD or some other rescue disk to correct configuration errors and reinstall GRUB. However, such a boot disk is not always available (nor necessary); the rescue console is surprisingly robust.<br />
<br />
The available commands in GRUB rescue include {{ic|insmod}}, {{ic|ls}}, {{ic|set}}, and {{ic|unset}}. This example uses {{ic|set}} and {{ic|insmod}}. {{ic|set}} modifies variables and {{ic|insmod}} inserts new modules to add functionality.<br />
<br />
Before starting, the user must know the location of their {{ic|/boot}} partition (be it a separate partition, or a subdirectory under their root):<br />
<br />
grub rescue> set prefix=(hdX,Y)/boot/grub<br />
<br />
where X is the physical drive number and Y is the partition number.<br />
<br />
To expand console capabilities, insert the {{ic|linux}} module:<br />
grub rescue> insmod i386-pc/linux.mod<br />
<br />
{{Note|With a separate boot partition, omit {{ic|/boot}} from the path, (i.e. type {{ic|1=set prefix=(hdX,Y)/grub}}).}}<br />
<br />
This introduces the {{ic|linux}} and {{ic|initrd}} commands, which should be familiar.<br />
<br />
An example, booting Arch Linux:<br />
<br />
set root=(hd0,5)<br />
linux /boot/vmlinuz-linux root=/dev/sda5<br />
initrd /boot/initramfs-linux.img<br />
boot<br />
<br />
With a separate boot partition, again change the lines accordingly:<br />
<br />
set root=(hd0,5)<br />
linux /vmlinuz-linux root=/dev/sda6<br />
initrd /initramfs-linux.img<br />
boot<br />
<br />
{{Note|If you experienced {{ic|error: premature end of file /YOUR_KERNEL_NAME}} during execution of {{ic|linux}} command, you can try {{ic|linux16}} instead.}}<br />
<br />
After successfully booting the Arch Linux installation, users can correct {{ic|grub.cfg}} as needed and then reinstall GRUB.<br />
<br />
To reinstall GRUB and fix the problem completely, changing {{ic|/dev/sda}} if needed. See [[#Installation]] for details.<br />
<br />
== Troubleshooting ==<br />
<br />
=== Intel BIOS not booting GPT ===<br />
<br />
==== MBR ====<br />
<br />
Some Intel BIOS's require at least one bootable MBR partition to be present at boot, causing GPT-partitioned boot setups to be unbootable.<br />
<br />
This can be circumvented by using (for instance) fdisk to mark one of the GPT partitions (preferably the 1007 KiB partition you have created for GRUB already) bootable in the MBR. This can be achieved, using fdisk, by the following commands: Start fdisk against the disk you are installing, for instance {{ic|fdisk /dev/sda}}, then press {{ic|a}} and select the partition you wish to mark as bootable (probably #1) by pressing the corresponding number, finally press {{ic|w}} to write the changes to the MBR.<br />
<br />
{{Note|The bootable-marking must be done in {{ic|fdisk}} or similar, not in GParted or others, as they will not set the bootable flag in the MBR.}}<br />
<br />
With cfdisk, the steps are similar, just {{ic|cfdisk /dev/sda}}, choose bootable (at the left) in the desired hard disk, and quit saving.<br />
<br />
More information is available [http://www.rodsbooks.com/gdisk/bios.html here]<br />
<br />
==== EFI path ====<br />
<br />
Some UEFI firmwares require a bootable file at a known location before they will show UEFI NVRAM boot entries. If this is the case, {{ic|grub-install}} will claim {{ic|efibootmgr}} has added an entry to boot GRUB, however the entry will not show up in the VisualBIOS boot order selector. The solution is to place a file at one of the known locations. Assuming the EFI partition is at {{ic|/boot/efi/}} this will work:<br />
<br />
mkdir /boot/efi/EFI/boot<br />
cp /boot/efi/EFI/grub/grubx64.efi /boot/efi/EFI/boot/bootx64.efi<br />
<br />
This solution worked for an Intel DH87MC motherboard with firmware dated Jan 2014.<br />
<br />
=== Enable debug messages ===<br />
<br />
{{Note|This change is overwritten when [[#Generate the main configuration file]].}}<br />
<br />
Add:<br />
<br />
set pager=1<br />
set debug=all<br />
<br />
to {{ic|grub.cfg}}.<br />
<br />
=== "No suitable mode found" error ===<br />
<br />
If you get this error when booting any menuentry:<br />
<br />
error: no suitable mode found<br />
Booting however<br />
<br />
Then you need to initialize GRUB graphical terminal ({{ic|gfxterm}}) with proper video mode ({{ic|gfxmode}}) in GRUB. This video mode is passed by GRUB to the linux kernel via 'gfxpayload'. In case of UEFI systems, if the GRUB video mode is not initialized, no kernel boot messages will be shown in the terminal (atleast until KMS kicks in).<br />
<br />
Copy {{ic|/usr/share/grub/unicode.pf2}} to ${GRUB_PREFIX_DIR} ({{ic|/boot/grub/}} in case of BIOS and UEFI systems). If GRUB UEFI was installed with {{ic|1=--boot-directory=$esp/EFI}} set, then the directory is {{ic|$esp/EFI/grub/}}:<br />
<br />
# cp /usr/share/grub/unicode.pf2 ${GRUB_PREFIX_DIR}<br />
<br />
If {{ic|/usr/share/grub/unicode.pf2}} does not exist, install {{Pkg|bdf-unifont}}, create the {{ic|unifont.pf2}} file and then copy it to {{ic|${GRUB_PREFIX_DIR<nowiki>}</nowiki>}}:<br />
<br />
# grub-mkfont -o unicode.pf2 /usr/share/fonts/misc/unifont.bdf<br />
<br />
Then, in the {{ic|grub.cfg}} file, add the following lines to enable GRUB to pass the video mode correctly to the kernel, without of which you will only get a black screen (no output) but booting (actually) proceeds successfully without any system hang.<br />
<br />
BIOS systems:<br />
<br />
insmod vbe<br />
<br />
UEFI systems:<br />
<br />
insmod efi_gop<br />
insmod efi_uga<br />
<br />
After that add the following code (common to both BIOS and UEFI):<br />
<br />
insmod font<br />
<br />
if loadfont ${prefix}/fonts/unicode.pf2<br />
then<br />
insmod gfxterm<br />
set gfxmode=auto<br />
set gfxpayload=keep<br />
terminal_output gfxterm<br />
fi<br />
<br />
As you can see for gfxterm (graphical terminal) to function properly, {{ic|unicode.pf2}} font file should exist in {{ic|${GRUB_PREFIX_DIR<nowiki>}</nowiki>}}.<br />
<br />
=== msdos-style error message ===<br />
<br />
grub-setup: warn: This msdos-style partition label has no post-MBR gap; embedding will not be possible!<br />
grub-setup: warn: Embedding is not possible. GRUB can only be installed in this setup by using blocklists.<br />
However, blocklists are UNRELIABLE and its use is discouraged.<br />
grub-setup: error: If you really want blocklists, use --force.<br />
<br />
This error may occur when you try installing GRUB in a VMware container. Read more about it [https://bbs.archlinux.org/viewtopic.php?pid=581760#p581760 here]. It happens when the first partition starts just after the MBR (block 63), without the usual space of 1 MiB (2048 blocks) before the first partition. Read [[#Master Boot Record (MBR) specific instructions]]<br />
<br />
=== UEFI ===<br />
<br />
==== Common installation errors ====<br />
<br />
* If you have a problem when running grub-install with sysfs or procfs and it says you must run {{ic|modprobe efivars}}, try [[Unified Extensible Firmware Interface#Switch to efivarfs]].<br />
* Without {{ic|--target}} or {{ic|--directory}} option, grub-install cannot determine for which firmware to install. In such cases {{ic|grub-install}} will print {{ic|source_dir does not exist. Please specify --target or --directory}}.<br />
* If after running grub-install you are told your partition does not look like an EFI partition then the partition is most likely not {{ic|Fat32}}.<br />
<br />
==== Drop to rescue shell ====<br />
<br />
If GRUB loads but drops you into the rescue shell with no errors, it may be because of a missing or misplaced {{ic|grub.cfg}}. This will happen if GRUB UEFI was installed with {{ic|--boot-directory}} and {{ic|grub.cfg}} is missing OR if the partition number of the boot partition changed (which is hard-coded into the {{ic|grubx64.efi}} file).<br />
<br />
==== GRUB UEFI not loaded ====<br />
<br />
An example of a working EFI:<br />
<br />
{{hc|# efibootmgr -v|<br />
BootCurrent: 0000<br />
Timeout: 3 seconds<br />
BootOrder: 0000,0001,0002<br />
Boot0000* Grub HD(1,800,32000,23532fbb-1bfa-4e46-851a-b494bfe9478c)File(\efi\grub\grub.efi)<br />
Boot0001* Shell HD(1,800,32000,23532fbb-1bfa-4e46-851a-b494bfe9478c)File(\EfiShell.efi)<br />
Boot0002* Festplatte BIOS(2,0,00)P0: SAMSUNG HD204UI<br />
}}<br />
<br />
If the screen only goes black for a second and the next boot option is tried afterwards, according to [https://bbs.archlinux.org/viewtopic.php?pid=981560#p981560 this post], moving GRUB to the partition root can help. The boot option has to be deleted and recreated afterwards. The entry for GRUB should look like this then:<br />
<br />
Boot0000* Grub HD(1,800,32000,23532fbb-1bfa-4e46-851a-b494bfe9478c)File(\grub.efi)<br />
<br />
=== Invalid signature ===<br />
<br />
If trying to boot Windows results in an "invalid signature" error, e.g. after reconfiguring partitions or adding additional hard drives, (re)move GRUB's device configuration and let it reconfigure:<br />
<br />
# mv /boot/grub/device.map /boot/grub/device.map-old<br />
# grub-mkconfig -o /boot/grub/grub.cfg<br />
<br />
{{ic|grub-mkconfig}} should now mention all found boot options, including Windows. If it works, remove {{ic|/boot/grub/device.map-old}}.<br />
<br />
=== Boot freezes ===<br />
<br />
If booting gets stuck without any error message after GRUB loading the kernel and the initial ramdisk, try removing the {{ic|add_efi_memmap}} kernel parameter.<br />
<br />
=== Arch not found from other OS ===<br />
<br />
Some have reported that other distributions have trouble finding Arch Linux automatically with {{ic|os-prober}}. If this problem arises, it has been reported that detection can be improved with the presence of {{ic|/etc/lsb-release}}. This file and updating tool is available with the package {{Pkg|lsb-release}} in the [[official repositories]].<br />
<br />
=== Warning when installing in chroot ===<br />
<br />
When installing GRUB on a LVM system in a chroot environment (e.g. during system installation), you may receive warnings like {{ic|/run/lvm/lvmetad.socket: connect failed: No such file or directory}} or {{ic|WARNING: failed to connect to lvmetad: No such file or directory. Falling back to internal scanning.}} This is because {{ic|/run}} is not available inside the chroot. These warnings will not prevent the system from booting, provided that everything has been done correctly, so you may continue with the installation.<br />
<br />
=== GRUB loads slowly ===<br />
<br />
GRUB can take a long time to load when disk space is low. Check if you have sufficient free disk space on your {{ic|/boot}} or {{ic|/}} partition when you are having problems.<br />
<br />
=== error: unknown filesystem ===<br />
GRUB may output {{ic|error: unknown filesystem}} and refuse to boot for a few reasons. If you are certain that all [[UUID]]s are correct and all filesystems are valid and supported, it may be because your [[#GUID_Partition_Table_.28GPT.29_specific_instructions|BIOS Boot Partition]] is located outside the first 2TB of the drive [https://bbs.archlinux.org/viewtopic.php?id=195948]. Use a partitioning tool of your choice to ensure this partition is located fully within the first 2TB, then reinstall and reconfigure GRUB.<br />
<br />
=== grub-reboot not resetting ===<br />
<br />
GRUB seems to be unable to write to root BTRFS partitions [https://bbs.archlinux.org/viewtopic.php?id=166131]. If you use grub-reboot to boot into another entry it will therefore be unable to update its on-disk environment. Either run grub-reboot from the other entry (for example when switching between various distributions) or consider a different file system. You can reset a "sticky" entry by executing {{ic|grub-editenv create}} and setting {{ic|GRUB_DEFAULT<nowiki>=</nowiki>0}} in your {{ic|/etc/default/grub}} (don't forget {{ic|grub-mkconfig}}).<br />
<br />
=== Old BTRFS prevents installation ===<br />
<br />
If a drive is formatted with BTRFS without creating a partition table (eg. /dev/sdx), then later has partition table written to, there are parts of the BTRFS format that persist. Most utilities and OS's do not see this, but GRUB will refuse to install, even with --force<br />
<br />
# grub-install: warning: Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet..<br />
# grub-install: error: filesystem `btrfs' doesn't support blocklists.<br />
<br />
You can zero the drive, but the easy solution that leaves your data alone is to erase the BTRFS superblock with {{ic|wipefs -o 0x10040 /dev/sdx}}<br />
<br />
== See also ==<br />
<br />
* Official GRUB Manual - https://www.gnu.org/software/grub/manual/grub.html<br />
* Ubuntu wiki page for GRUB - https://help.ubuntu.com/community/Grub2<br />
* GRUB wiki page describing steps to compile for UEFI systems - https://help.ubuntu.com/community/UEFIBooting<br />
* Wikipedia's page on [[Wikipedia:BIOS Boot partition|BIOS Boot partition]]<br />
* http://members.iinet.net/~herman546/p20/GRUB2%20Configuration%20File%20Commands.html - quite complete description of how to configure GRUB</div>Stbinanhttps://wiki.archlinux.org/index.php?title=GRUB&diff=414910GRUB2016-01-11T05:18:24Z<p>Stbinan: /* Dual-booting */</p>
<hr />
<div>[[Category:Boot loaders]]<br />
[[ar:GRUB]]<br />
[[cs:GRUB]]<br />
[[de:GRUB]]<br />
[[el:GRUB]]<br />
[[es:GRUB]]<br />
[[fr:GRUB]]<br />
[[he:GRUB]]<br />
[[id:GRUB]]<br />
[[it:GRUB]]<br />
[[ja:GRUB]]<br />
[[nl:GRUB]]<br />
[[pt:GRUB]]<br />
[[ru:GRUB]]<br />
[[tr:GRUB2]]<br />
[[uk:GRUB]]<br />
[[zh-cn:GRUB]]<br />
[[zh-tw:GRUB]]<br />
{{Related articles start}}<br />
{{Related|Arch boot process}}<br />
{{Related|Boot loaders}}<br />
{{Related|Master Boot Record}}<br />
{{Related|GUID Partition Table}}<br />
{{Related|Unified Extensible Firmware Interface}}<br />
{{Related|GRUB Legacy}}<br />
{{Related|GRUB/EFI examples}}<br />
{{Related|GRUB/Tips and tricks}}<br />
{{Related articles end}}<br />
[https://www.gnu.org/software/grub/ GRUB] — not to be confused with [[GRUB Legacy]] — is the next generation of the GRand Unified Bootloader. GRUB is derived from [http://www.nongnu.org/pupa/ PUPA] which was a research project to develop the next generation of what is now GRUB Legacy. GRUB has been rewritten from scratch to clean up everything and provide modularity and portability [https://www.gnu.org/software/grub/grub-faq.html#q1].<br />
<br />
== Preface ==<br />
<br />
* A ''bootloader'' is the first software program that runs when a computer starts. It is responsible for loading and transferring control to the Linux kernel. The kernel, in turn, initializes the rest of the operating system.<br />
* The name ''GRUB'' officially refers to version ''2'' of the software, see [https://www.gnu.org/software/grub/]. If you are looking for the article on the legacy version, see [[GRUB Legacy]].<br />
* GRUB supports [[Btrfs]] as root (without a separate {{ic|/boot}} file system) compressed with either zlib or LZO<br />
** GRUB currently (Sep 2015) supports booting from [[Btrfs]] RAID 0/1/10, but ''not'' RAID 5/6. You may use [[mdadm]] for RAID 5/6, which is supported by GRUB.<br />
* GRUB does not support [[F2FS]] as root so you will need a separate {{ic|/boot}} with a supported file system.<br />
<br />
== BIOS systems ==<br />
<br />
=== GUID Partition Table (GPT) specific instructions ===<br />
<br />
On a BIOS/[[GPT]] configuration a [http://www.gnu.org/software/grub/manual/html_node/BIOS-installation.html BIOS boot partition] is required. GRUB embeds its {{ic|core.img}} into this partition.<br />
<br />
{{Note|<br />
* Before attempting this method keep in mind that not all systems will be able to support this partitioning scheme, read more on [[GUID Partition Table#BIOS systems|GUID partition tables]].<br />
* This additional partition is only needed on a GRUB, BIOS/GPT partitioning scheme. Previously, for a GRUB, BIOS/MBR partitioning scheme, GRUB used the Post-MBR gap for the embedding the {{ic|core.img}}). GRUB for GPT, however, does not use the Post-GPT gap to conform to GPT specifications that require 1_megabyte/2048_sector disk boundaries.<br />
* For [[UEFI]] systems this extra partition is not required as no embedding of boot sectors takes place in that case.<br />
}}<br />
<br />
Create a mebibyte partition ({{ic|1=+1M}} with {{ic|fdisk}} or {{ic|gdisk}}) on the disk with no file system and type BIOS boot (''BIOS boot'' in fdisk, {{ic|ef02}} in gdisk, {{ic|bios_grub}} in {{ic|parted}}). This partition can be in any position order but has to be on the first 2 TiB of the disk. This partition needs to be created before GRUB installation. When the partition is ready, install the bootloader as per the instructions below.<br />
<br />
The post-GPT gap can also be used as the BIOS boot partition though it will be out of GPT alignment specification. Since the partition will not be regularly accessed performance issues can be disregarded (though some disk utilities will display a warning about it). In {{ic|fdisk}} or {{ic|gdisk}} create a new partition starting at sector 34 and spanning to 2047 and set the type. To have the viewable partitions begin at the base consider adding this partition last.<br />
<br />
=== Master Boot Record (MBR) specific instructions ===<br />
<br />
Usually the post-[[MBR]] gap (after the 512 byte MBR region and before the start of the first partition) in many MBR (or 'msdos' disklabel) partitioned systems is 31 KiB when DOS compatibility cylinder alignment issues are satisfied in the partition table. However a post-MBR gap of about 1 to 2 MiB is recommended to provide sufficient room for embedding GRUB's {{ic|core.img}} ({{bug|24103}}). It is advisable to use a partitioning tool that supports 1 MiB partition alignment to obtain this space as well as to satisfy other non-512 byte sector issues (which are unrelated to embedding of {{ic|core.img}}).<br />
<br />
=== Installation ===<br />
<br />
[[Install]] the {{Pkg|grub}} package. It will replace {{AUR|grub-legacy}}, where already installed.<br />
<br />
{{Note|Simply installing the package will not update the {{ic|/boot/grub/i386-pc/core.img}} file and the GRUB modules in {{ic|/boot/grub/i386-pc}}. You need to update them manually using {{ic|grub-install}} as explained below.}}<br />
<br />
==== Install boot files ====<br />
<br />
There are 4 ways to install GRUB boot files in BIOS booting:<br />
<br />
* [[#Install to disk|Install to disk]] (recommended)<br />
* [[#Install to external USB stick|Install to external USB stick]] (for recovery)<br />
* [[#Install to partition or partitionless disk|Install to partition or partitionless disk]] (not recommended)<br />
* [[#Generate core.img alone|Generate core.img alone]] (safest method, but requires another BIOS bootloader like [[Syslinux]] to be installed to chainload {{ic|/boot/grub/i386-pc/core.img}})<br />
<br />
{{Note|See https://www.gnu.org/software/grub/manual/html_node/BIOS-installation.html for additional documentation.}}<br />
<br />
===== Install to disk =====<br />
<br />
{{Note|The method is specific to installing GRUB to a partitioned (MBR or GPT) disk, with GRUB files installed to {{ic|/boot/grub}} and its first stage code installed to the 440-byte MBR boot code region (not to be confused with MBR partition table). }}<br />
<br />
The following commands will:<br />
* Set up GRUB in the 440-byte Master Boot Record boot code region<br />
* Populate the {{ic|/boot/grub}} directory<br />
* Generate the {{ic|/boot/grub/i386-pc/core.img}} file<br />
* Embed it in the 31 KiB (minimum size - varies depending on partition alignment) post-MBR gap in case of MBR partitioned disk<br />
* In the case of a GPT partitioned disk it will embed it in the BIOS Boot Partition , denoted by {{ic|bios_grub}} flag in parted and EF02 type code in gdisk<br />
<br />
# grub-install --recheck --target=i386-pc /dev/sd''x''<br />
# grub-mkconfig -o /boot/grub/grub.cfg<br />
<br />
If you use [[LVM]] for your {{ic|/boot}}, you can install GRUB on multiple physical disks.<br />
<br />
===== Install to external USB stick =====<br />
<br />
Assume your USB stick's first partition is FAT32 and its partition is /dev/sdy1<br />
<br />
# mkdir -p /mnt/usb ; mount /dev/sdy1 /mnt/usb<br />
# grub-install --target=i386-pc --recheck --debug --boot-directory=/mnt/usb/boot /dev/sdy<br />
# grub-mkconfig -o /mnt/usb/boot/grub/grub.cfg<br />
<br />
# optional, backup config files of grub.cfg<br />
# mkdir -p /mnt/usb/etc/default<br />
# cp /etc/default/grub /mnt/usb/etc/default<br />
# cp -a /etc/grub.d /mnt/usb/etc<br />
<br />
# sync; umount /mnt/usb<br />
<br />
===== Install to partition or partitionless disk =====<br />
{{Warning|GRUB '''strongly discourages''' installation to a partition boot sector or a partitionless disk as GRUB Legacy or Syslinux does. This setup is prone to breakage, especially during updates, and is '''not supported''' by the Arch developers.}}<br />
<br />
To set up grub to a partition boot sector, to a partitionless disk (also called superfloppy) or to a floppy disk, run (using for example {{ic|/dev/sdaX}} as the {{ic|/boot}} partition):<br />
<br />
# chattr -i /boot/grub/i386-pc/core.img<br />
# grub-install --target=i386-pc --recheck --debug --force /dev/sdaX<br />
# chattr +i /boot/grub/i386-pc/core.img<br />
<br />
{{Note|<br />
* {{ic|/dev/sdaX}} used for example only.<br />
* {{ic|1=--target=i386-pc}} instructs {{ic|grub-install}} to install for BIOS systems only. It is recommended to always use this option to remove ambiguity in ''grub-install''.<br />
}}<br />
<br />
You need to use the {{ic|--force}} option to allow usage of blocklists and should not use {{ic|1=--grub-setup=/bin/true}} (which is similar to simply generating {{ic|core.img}}).<br />
<br />
{{ic|grub-install}} will give out warnings like which should give you the idea of what might go wrong with this approach:<br />
<br />
/sbin/grub-setup: warn: Attempting to install GRUB to a partitionless disk or to a partition. This is a BAD idea.<br />
/sbin/grub-setup: warn: Embedding is not possible. GRUB can only be installed in this setup by using blocklists.<br />
However, blocklists are UNRELIABLE and their use is discouraged.<br />
<br />
Without {{ic|--force}} you may get the below error and {{ic|grub-setup}} will not setup its boot code in the partition boot sector:<br />
<br />
/sbin/grub-setup: error: will not proceed with blocklists<br />
<br />
With {{ic|--force}} you should get:<br />
<br />
Installation finished. No error reported.<br />
<br />
The reason why {{ic|grub-setup}} does not by default allow this is because in case of partition or a partitionless disk is that GRUB relies on embedded blocklists in the partition bootsector to locate the {{ic|/boot/grub/i386-pc/core.img}} file and the prefix directory {{ic|/boot/grub}}. The sector locations of {{ic|core.img}} may change whenever the file system in the partition is being altered (files copied, deleted etc.). For more info, see https://bugzilla.redhat.com/show_bug.cgi?id=728742 and https://bugzilla.redhat.com/show_bug.cgi?id=730915.<br />
<br />
The workaround for this is to set the immutable flag on {{ic|/boot/grub/i386-pc/core.img}} (using {{ic|chattr}} command as mentioned above) so that the sector locations of the {{ic|core.img}} file in the disk is not altered. The immutable flag on {{ic|/boot/grub/i386-pc/core.img}} needs to be set only if GRUB is installed to a partition boot sector or a partitionless disk, not in case of installation to MBR or simple generation of {{ic|core.img}} without embedding any bootsector (mentioned above).<br />
<br />
Unfortunately, the {{ic|grub.cfg}} file that is created will not contain the proper UUID in order to boot, even if it reports no errors. see https://bbs.archlinux.org/viewtopic.php?pid=1294604#p1294604.<br />
In order to fix this issue the following commands:<br />
<br />
# mount /dev/sdxY /mnt #Your root partition.<br />
# mount /dev/sdxZ /mnt/boot #Your boot partition (if you have one).<br />
# arch-chroot /mnt<br />
# pacman -S linux<br />
# grub-mkconfig -o /boot/grub/grub.cfg<br />
<br />
===== Generate core.img alone =====<br />
<br />
To populate the {{ic|/boot/grub}} directory and generate a {{ic|/boot/grub/i386-pc/core.img}} file '''without''' embedding any GRUB bootsector code in the MBR, post-MBR region, or the partition bootsector, add {{ic|1=--grub-setup=/bin/true}} to {{ic|grub-install}}:<br />
<br />
# grub-install --target=i386-pc --grub-setup=/bin/true --recheck --debug /dev/sda<br />
<br />
{{Note|<br />
* {{ic|/dev/sda}} used for example only.<br />
* {{ic|1=--target=i386-pc}} instructs {{ic|grub-install}} to install for BIOS systems only. It is recommended to always use this option to remove ambiguity in grub-install.<br />
}}<br />
<br />
You can then chainload GRUB's {{ic|core.img}} from GRUB Legacy or syslinux as a Linux kernel or as a multiboot kernel (see also [[Syslinux#Chainloading]]).<br />
<br />
== UEFI systems ==<br />
<br />
{{Note|<br />
* It is recommended to read and understand the [[UEFI]], [[GPT]] and [[UEFI Bootloaders]] pages.<br />
* When installing to use UEFI it is important to start the install with your machine in UEFI mode. The Arch Linux install media must be UEFI bootable.<br />
}}<br />
<br />
=== Check if you have GPT and an ESP ===<br />
<br />
An EFI System Partition (ESP) is needed on every disc you want to boot using EFI. GPT is not strictly necessary, but it is highly recommended and is the only method currently supported in this article. If you are installing Arch Linux on an EFI-capable computer with an already-working operating system, like Windows 8 for example, it is very likely that you already have an ESP. To check for GPT and for an ESP, use {{ic|parted}} as root to print the partition table of the disk you want to boot from. (We are calling it {{ic|/dev/sda}}.)<br />
<br />
# parted /dev/sda print<br />
<br />
For GPT, you are looking for "Partition Table: GPT". For EFI, you are looking for a small (512 MiB or less) partition with a vfat file system and the ''boot'' flag enabled. On it, there should be a directory named "EFI". If these criteria are met, this is your ESP. Make note of the partition number. You will need to know which one it is, so you can mount it later on while installing GRUB to it.<br />
<br />
=== Create an ESP ===<br />
<br />
If you do not have an ESP, you will need to create one. See [[UEFI#EFI System Partition]]<br />
<br />
=== Installation ===<br />
<br />
{{Note|UEFI firmware are not implemented consistently by hardware manufacturers. The installation examples provided are intended to work on the widest range of UEFI systems possible. Those experiencing problems despite applying these methods are encouraged to share detailed information for their hardware-specific cases, especially where solving these problems. A [[GRUB/EFI examples]] article has been provided for such cases.}}<br />
<br />
This section assumes you are installing GRUB for x86_64 systems (x86_64-efi). For i686 systems, replace {{ic|x86_64-efi}} with {{ic|i386-efi}} where appropriate.<br />
<br />
Make sure you are in a [[bash]] shell. For example, when booting from the Arch ISO:<br />
<br />
# arch-chroot /mnt /bin/bash<br />
<br />
[[Install]] the packages {{Pkg|grub}} and {{Pkg|efibootmgr}}. ''GRUB'' is the bootloader, ''efibootmgr'' creates bootable {{ic|.efi}} stub entries used by the GRUB installation script.<br />
<br />
The following steps install the GRUB UEFI application to {{ic|'''$esp'''/EFI/grub}}, install its modules to {{ic|/boot/grub/x86_64-efi}}, and place the bootable {{ic|grubx64.efi}} stub in {{ic|'''$esp'''/EFI/grub}}.<br />
<br />
First, tell GRUB to use UEFI, set the boot directory and set the bootloader ID. Change {{ic|$esp}} to your efi partition (usually {{ic|/boot}}):<br />
<br />
# grub-install --target=x86_64-efi --efi-directory='''$esp''' --bootloader-id='''grub''' --recheck<br />
<br />
The {{ic|--bootloader-id}} is what appears in the boot options to identity the GRUB EFI boot option; make sure this is something you will recognize later. The install will create a directory of the same name under {{ic|$esp/EFI/}} where the EFI binary bootloader will be placed. <br />
<br />
After the above install finished the main GRUB directory is located at {{ic|/boot/grub/}}. <br />
<br />
Remember to [[#Generate the main configuration file]] after finalizing further setup dependant [[#Configuration]]. <br />
<br />
{{Note|<br />
* While some distributions require a {{ic|/boot/efi}} or {{ic|/boot/EFI}} directory, Arch does not.<br />
* {{ic|--efi-directory}} and {{ic|--bootloader-id}} are specific to GRUB UEFI. {{ic|--efi-directory}} specifies the mountpoint of the ESP. It replaces {{ic|--root-directory}}, which is deprecated. <br />
* You might note the absence of a <device_path> option (e.g.: {{ic|/dev/sda}}) in the {{ic|grub-install}} command. In fact any <device_path> provided will be ignored by the GRUB install script, as UEFI bootloaders do not use a MBR or partition boot sector at all.<br />
}}<br />
<br />
See [[#UEFI|UEFI troubleshooting]] in case of problems.<br />
<br />
=== Further reading ===<br />
<br />
Below is other relevant information regarding installing Arch via UEFI<br />
<br />
==== Alternative install method ====<br />
<br />
Usually, GRUB keeps all files, including configuration files, in {{ic|/boot}}, regardless of where the EFI System Partition is mounted.<br />
<br />
If you want to keep these files inside the EFI System Partition itself, add {{ic|--boot-directory&#61;$esp}} to the grub-install command:<br />
<br />
# grub-install --target=x86_64-efi --efi-directory=$esp --bootloader-id=grub --boot-directory=$esp --recheck --debug<br />
<br />
This puts all GRUB files in {{ic|$esp/grub}}, instead of in {{ic|/boot/grub}}. When using this method, make sure you have ''grub-mkconfig'' put the configuration file in same place:<br />
<br />
# grub-mkconfig -o $esp/grub/grub.cfg<br />
<br />
Configuration is otherwise the same.<br />
<br />
==== UEFI firmware workaround ====<br />
<br />
Some UEFI firmware requires that the bootable {{ic|.efi}} stub have a specific name and be placed in a specific location: {{ic|$esp/EFI/boot/bootx64.efi}} (where {{ic|$esp}} is the UEFI partition mountpoint). Failure to do so in such instances will result in an unbootable installation. Fortunately, this will not cause any problems with other firmware that does not require this.<br />
<br />
To do so, first create the necessary directory, and then copy across the grub {{ic|.efi}} stub, renaming it in the process:<br />
<br />
# mkdir $esp/EFI/boot<br />
# cp $esp/EFI/grub_uefi/grubx64.efi $esp/EFI/boot/bootx64.efi<br />
<br />
==== Create a GRUB entry in the firmware boot manager ====<br />
{{ic|grub-install}} automatically tries to create a menu entry in the boot manager. If it does not, then see [[UEFI#efibootmgr]] for instructions to use {{ic|efibootmgr}} to create a menu entry. However, the problem is likely to be that you have not booted your CD/USB in UEFI mode, as in [[UEFI#Create UEFI bootable USB from ISO]].<br />
<br />
==== GRUB standalone ====<br />
<br />
This section assumes you are creating a standalone GRUB for x86_64 systems (x86_64-efi). For i686 systems, replace {{ic|x86_64-efi}} with {{ic|i386-efi}} where appropriate.<br />
<br />
It is possible to create a {{ic|grubx64_standalone.efi}} application which has all the modules embedded in a tar archive within the UEFI application, thus removing the need for having a separate directory populated with all of the GRUB UEFI modules and other related files. This is done using the {{ic|grub-mkstandalone}} command (included in {{Pkg|grub}}) as follows:<br />
<br />
# echo 'configfile ${cmdpath}/grub.cfg' > /tmp/grub.cfg<br />
# grub-mkstandalone -d /usr/lib/grub/x86_64-efi/ -O x86_64-efi --modules="part_gpt part_msdos" --fonts="unicode" --locales="en@quot" --themes="" -o "$esp/EFI/grub/grubx64_standalone.efi" "boot/grub/grub.cfg=/tmp/grub.cfg" -v<br />
<br />
Then copy the GRUB config file to {{ic|$esp/EFI/grub/grub.cfg}} and create a UEFI Boot Manager entry for {{ic|$esp/EFI/grub/grubx64_standalone.efi}} using [[UEFI#efibootmgr|efibootmgr]].<br />
<br />
{{Note|<br />
The option {{ic|1=--modules="part_gpt part_msdos"}} (with the quotes) is necessary for the {{ic|${cmdpath} }} feature to work properly.<br />
}}<br />
<br />
{{Warning|You may find that the {{ic|grub.cfg}} file is not loaded due to {{ic|${cmdpath} }} missing a slash (i.e. {{ic|(hd1,msdos2)EFI/Boot}} instead of {{ic|(hd1,msdos2)/EFI/Boot}}) and so you are dropped into a GRUB shell. If this happens determine what {{ic|${cmdpath} }} is set to ({{ic|echo ${cmdpath} }}) and then load the config file manually (e.g. {{ic|configfile (hd1,msdos2)/EFI/Boot/grub.cfg}}).}}<br />
<br />
==== Technical information ====<br />
<br />
The GRUB EFI file always expects its config file to be at {{ic|${prefix}/grub.cfg}}. However in the standalone GRUB EFI file, the {{ic|${prefix} }} is located inside a tar archive and embedded inside the standalone GRUB EFI file itself (inside the GRUB environment, it is denoted by {{ic|"(memdisk)"}}, without quotes). This tar archive contains all the files that would be stored normally at {{ic|/boot/grub}} in case of a normal GRUB EFI install.<br />
<br />
Due to this embedding of {{ic|/boot/grub}} contents inside the standalone image itself, it does not rely on actual (external) {{ic|/boot/grub}} for anything. Thus in case of standalone GRUB EFI file {{ic|1=${prefix}==(memdisk)/boot/grub}} and the standalone GRUB EFI file reads expects the config file to be at {{ic|1=${prefix}/grub.cfg==(memdisk)/boot/grub/grub.cfg}}.<br />
<br />
Hence to make sure the standalone GRUB EFI file reads the external {{ic|grub.cfg}} located in the same directory as the EFI file (inside the GRUB environment, it is denoted by {{ic|${cmdpath} }}), we create a simple {{ic|/tmp/grub.cfg}} which instructs GRUB to use {{ic|${cmdpath}/grub.cfg}} as its config ({{ic|configfile ${cmdpath}/grub.cfg}} command in {{ic|(memdisk)/boot/grub/grub.cfg}}). We then instruct grub-mkstandalone to copy this {{ic|/tmp/grub.cfg}} file to {{ic|${prefix}/grub.cfg}} (which is actually {{ic|(memdisk)/boot/grub/grub.cfg}}) using the option {{ic|1="boot/grub/grub.cfg=/tmp/grub.cfg"}}.<br />
<br />
This way, the standalone GRUB EFI file and actual {{ic|grub.cfg}} can be stored in any directory inside the EFI System Partition (as long as they are in the same directory), thus making them portable.<br />
<br />
== Generate the main configuration file ==<br />
<br />
After the installation, the main configuration file {{ic|grub.cfg}} needs to be generated. The generation process can be influenced by a variety of options in {{ic|/etc/default/grub}} and scripts in {{ic|/etc/grub.d/}}; see [[#Configuration]]. <br />
<br />
If you have not done additional configuration, the automatic generation will determine the root filesystem of the system to boot for the configuration file. For that to succeed it is important that the system is either booted or chrooted into. <br />
<br />
{{Note|Remember that {{ic|grub.cfg}} has to be re-generated after any change to {{ic|/etc/default/grub}} or files in {{ic|/etc/grub.d/}}.}}<br />
<br />
Use the ''grub-mkconfig'' tool to generate {{ic|grub.cfg}}:<br />
<br />
# grub-mkconfig -o /boot/grub/grub.cfg<br />
<br />
{{Note|<br />
* The default file path is {{ic|/boot/grub/grub.cfg}}, not {{ic|/boot/grub/i386-pc/grub.cfg}}. The {{Pkg|grub}} includes a sample {{ic|/boot/grub/grub.cfg}}; ensure your intended changes were written to this file.<br />
* If you are trying to run ''grub-mkconfig'' in a chroot or ''systemd-nspawn'' container, you might notice that it does not work, complaining that ''grub-probe'' cannot get the "canonical path of /dev/sdaX". In this case, try using ''arch-chroot'' as described in the [https://bbs.archlinux.org/viewtopic.php?pid&#61;1225067#p1225067 BBS post].<br />
}}<br />
<br />
By default the generation scripts automatically add menu entries for Arch Linux to any generated configuration. See [[#Dual-booting]] for configuration with other systems.<br />
<br />
== Configuration ==<br />
<br />
This section only covers editing the {{ic|/etc/default/grub}} configuration file. See [[GRUB/Tips and tricks]] for more information.<br />
<br />
Remember to always [[#Generate the main configuration file]] after making changes to {{ic|/etc/default/grub}}.<br />
<br />
=== Additional arguments ===<br />
<br />
To pass custom additional arguments to the Linux image, you can set the {{ic|GRUB_CMDLINE_LINUX}} + {{ic|GRUB_CMDLINE_LINUX_DEFAULT}} variables in {{ic|/etc/default/grub}}. The two are appended to each other and passed to kernel when generating regular boot entries. For the ''recovery'' boot entry, only {{ic|GRUB_CMDLINE_LINUX}} is used in the generation.<br />
<br />
It is not necessary to use both, but can be useful. For example, you could use {{ic|<nowiki>GRUB_CMDLINE_LINUX_DEFAULT="resume=/dev/sdaX</nowiki> quiet"}} where {{ic|sda'''X'''}} is your swap partition to enable resume after hibernation. This would generate a recovery boot entry without the resume and without ''quiet'' suppressing kernel messages during a boot from that menu entry. Though, the other (regular) menu entries would have them as options.<br />
<br />
By default ''grub-mkconfig'' determines the [[UUID]] of the root filesystem for the configuration. To disable this, uncomment {{ic|1=GRUB_DISABLE_LINUX_UUID=true}}. <br />
<br />
For generating the GRUB recovery entry you also have to comment out {{ic|<nowiki>#GRUB_DISABLE_RECOVERY=true</nowiki>}} in {{ic|/etc/default/grub}}.<br />
<br />
You can also use {{ic|<nowiki>GRUB_CMDLINE_LINUX="resume=UUID=uuid-of-swap-partition"</nowiki>}}<br />
<br />
See [[Kernel parameters]] for more info.<br />
<br />
=== Dual-booting ===<br />
<br />
{{Tip|To have ''grub-mkconfig'' search for other installed systems, [[install]] {{Pkg|os-prober}}.}}<br />
<br />
==== Automatically generating using /etc/grub.d/40_custom and grub-mkconfig ====<br />
<br />
The best way to add other entries is editing the {{ic|/etc/grub.d/40_custom}} or {{ic|/boot/grub/custom.cfg}}. The entries in this file will be automatically added when running {{ic|grub-mkconfig}}.<br />
After adding the new lines, run:<br />
{{bc|<nowiki># grub-mkconfig -o /boot/grub/grub.cfg</nowiki>}}<br />
or, for UEFI-GPT Mode (As per [[#Alternative install method]]):<br />
{{bc|<nowiki># grub-mkconfig -o /boot/efi/EFI/GRUB/grub.cfg</nowiki>}}<br />
to generate an updated {{ic|grub.cfg}}.<br />
<br />
For example, a typical {{ic|/etc/grub.d/40_custom}} file, could appear similar to the following one, created for [http://h10025.www1.hp.com/ewfrf/wc/product?cc=us&destPage=product&lc=en&product=5402703&tmp_docname= HP Pavilion 15-e056sl Notebook PC], originally with Microsoft Windows 8 preinstalled. Each {{ic|menuentry}} should maintain a structure similar to the following ones. Note that the UEFI partition {{ic|/dev/sda2}} within GRUB is called {{ic|hd0,gpt2}} and {{ic|ahci0,gpt2}} (see [[#Windows installed in UEFI-GPT Mode menu entry|here]] for more info).<br />
<br />
{{hc|/etc/grub.d/40_custom|<nowiki>#!/bin/sh<br />
exec tail -n +3 $0<br />
# This file provides an easy way to add custom menu entries.&nbsp; Simply type the<br />
# menu entries you want to add after this comment.&nbsp; Be careful not to change<br />
# the 'exec tail' line above.<br />
<br />
menuentry "HP / Microsoft Windows 8.1" {<br />
echo "Loading HP / Microsoft Windows 8.1..."<br />
insmod part_gpt<br />
insmod fat<br />
insmod search_fs_uuid<br />
insmod chain<br />
search --fs-uuid --no-floppy --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 763A-9CB6<br />
chainloader /EFI/Microsoft/Boot/bootmgfw.efi<br />
}<br />
<br />
menuentry "HP / Microsoft Control Center" {<br />
echo "Loading HP / Microsoft Control Center..."<br />
insmod part_gpt<br />
insmod fat<br />
insmod search_fs_uuid<br />
insmod chain<br />
search --fs-uuid --no-floppy --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 763A-9CB6<br />
chainloader /EFI/HP/boot/bootmgfw.efi<br />
}<br />
<br />
menuentry "System shutdown" {<br />
echo "System shutting down..."<br />
halt<br />
}<br />
<br />
menuentry "System restart" {<br />
echo "System rebooting..."<br />
reboot<br />
}</nowiki>}}<br />
<br />
===== GNU/Linux menu entry =====<br />
Assuming that the other distro is on partition {{ic|sda2}}:<br />
<br />
{{bc|<nowiki>menuentry "Other Linux" {<br />
set root=(hd0,2)<br />
linux /boot/vmlinuz (add other options here as required)<br />
initrd /boot/initrd.img (if the other kernel uses/needs one)<br />
}</nowiki>}}<br />
<br />
Alternatively let grub search for the right partition by ''UUID'' or ''label'':<br />
<br />
{{bc|<nowiki>menuentry "Other Linux" {<br />
# assuming that UUID is 763A-9CB6<br />
search --set=root --fs-uuid 763A-9CB6<br />
<br />
# search by label OTHER_LINUX (make sure that partition label is unambiguous)<br />
#search --set=root --label OTHER_LINUX<br />
<br />
linux /boot/vmlinuz (add other options here as required, for example: root=UUID=763A-9CB6)<br />
initrd /boot/initrd.img (if the other kernel uses/needs one)<br />
}</nowiki>}}<br />
<br />
===== FreeBSD menu entry =====<br />
The following three methods require that FreeBSD is installed on a single partition with UFS(v2). Assuming the nested BSD partition table is on {{ic|sda4}}:<br />
<br />
====== Loading the kernel directly ======<br />
{{bc|1=<br />
menuentry 'FreeBSD' {<br />
insmod ufs2<br />
set root='hd0,gpt4,bsd1'<br />
## or 'hd0,msdos4,bsd1', if using an IBM-PC (MS-DOS) style partition table<br />
kfreebsd /boot/kernel/kernel<br />
kfreebsd_loadenv /boot/device.hints<br />
set kFreeBSD.vfs.root.mountfrom=ufs:/dev/ada0s4a<br />
set kFreeBSD.vfs.root.mountfrom.options=rw<br />
}<br />
}}<br />
<br />
====== Chainloading the embedded boot record ======<br />
{{bc|1=<br />
menuentry 'FreeBSD' {<br />
insmod ufs2<br />
set root='hd0,gpt4,bsd1'<br />
chainloader +1<br />
}<br />
}}<br />
<br />
====== Running the traditional BSD 2nd stage loader ======<br />
{{bc|1=<br />
menuentry 'FreeBSD' {<br />
insmod ufs2<br />
set root='(hd0,4)'<br />
kfreebsd /boot/loader<br />
}<br />
}}<br />
<br />
===== Windows XP menu entry=====<br />
This assumes that your Windows partition is {{ic|sda3}}. Remember you need to point set root and chainloader to the system reserve partition that windows made when it installed, not the actual partition windows is on. This example works if your system reserve partition is {{ic|sda3}}.<br />
<br />
{{bc|<nowiki># (2) Windows XP<br />
menuentry "Windows XP" {<br />
set root="(hd0,3)"<br />
chainloader +1<br />
}</nowiki>}}<br />
<br />
If the Windows bootloader is on an entirely different hard drive than GRUB, it may be necessary to trick Windows into believing that it is the first hard drive. This was possible with {{ic|drivemap}}. Assuming GRUB is on {{ic|hd0}} and Windows is on {{ic|hd2}}, you need to add the following after {{ic|set root}}:<br />
<br />
{{bc|drivemap -s hd0 hd2}}<br />
<br />
===== Windows installed in UEFI-GPT Mode menu entry =====<br />
<br />
{{Note|This menuentry will work only in UEFI boot mode and only if the Windows bitness matches the UEFI bitness. It '''WILL NOT WORK''' in BIOS installed GRUB. See [[Dual boot with Windows#Windows UEFI vs BIOS limitations]] and [[Dual boot with Windows#Bootloader UEFI vs BIOS limitations]] for more info.}}<br />
<br />
{{bc|<nowiki>if [ "${grub_platform}" == "efi" ]; then<br />
menuentry "Microsoft Windows Vista/7/8/8.1 UEFI-GPT" {<br />
insmod part_gpt<br />
insmod fat<br />
insmod search_fs_uuid<br />
insmod chain<br />
search --fs-uuid --set=root $hints_string $fs_uuid<br />
chainloader /EFI/Microsoft/Boot/bootmgfw.efi<br />
}<br />
fi</nowiki>}}<br />
<br />
where {{ic|$hints_string}} and {{ic|$fs_uuid}} are obtained with the following two commands. {{ic|$fs_uuid}}'s command:<br />
<br />
{{hc|1=# grub-probe --target=fs_uuid $esp/EFI/Microsoft/Boot/bootmgfw.efi|2=<br />
1ce5-7f28<br />
}}<br />
<br />
{{ic|$hints_string}}'s command:<br />
<br />
{{hc|1=# grub-probe --target=hints_string $esp/EFI/Microsoft/Boot/bootmgfw.efi|2=<br />
--hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1<br />
}}<br />
<br />
These two commands assume the ESP Windows uses is mounted at {{ic|$esp}}. There might be case differences in the path to Windows's EFI file, what with being Windows, and all.<br />
<br />
===== "Guix" menu entry =====<br />
{{bc|<nowiki>menuentry "GNU with Linux-Libre 4.2.5 (alpha)" {<br />
search --set=root --fs-uuid YOUR_ROOT_PARTITION_UUID<br />
search --file --set /gnu/store/zbm09fk0wxkw2wyygnn4gcfxj8s31ajd-linux-libre-4.2.5/bzImage<br />
<br />
linux /gnu/store/zbm09fk0wxkw2wyygnn4gcfxj8s31ajd-linux-libre-4.2.5/bzImage --root=gnu --system=/gnu/store/a1brgzara5mw72jnmhqjx0j69ah8p5mp-system --load=/gnu/store/a1brgzara5mw72jnmhqjx0j69ah8p5mp-system/boot<br />
initrd /gnu/store/a1brgzara5mw72jnmhqjx0j69ah8p5mp-system/initrd<br />
}</nowiki>}}<br />
<br />
===== "Shutdown" menu entry =====<br />
<br />
{{bc|<nowiki>menuentry "System shutdown" {<br />
echo "System shutting down..."<br />
halt<br />
}</nowiki>}}<br />
<br />
===== "Restart" menu entry =====<br />
<br />
{{bc|<nowiki>menuentry "System restart" {<br />
echo "System rebooting..."<br />
reboot<br />
}</nowiki>}}<br />
<br />
===== Windows installed in BIOS-MBR mode =====<br />
<br />
{{Poor writing|This section does not fit into the others, should be slimmed down a bit.}}<br />
<br />
{{Note|GRUB supports booting {{ic|bootmgr}} directly and chainload of partition boot sector is no longer required to boot Windows in a BIOS-MBR setup.}}<br />
<br />
{{Warning|It is the '''system partition''' that has {{ic|/bootmgr}}, not your "real" Windows partition (usually C:). In {{ic|blkid}} output, the system partition is the one with {{ic|LABEL&#61;"SYSTEM RESERVED"}} or {{ic|LABEL&#61;"SYSTEM"}} and is only about 100 to 200 MB in size (much like the boot partition for Arch). See [[Wikipedia:System partition and boot partition]] for more info.}}<br />
<br />
Throughout this section, it is assumed your Windows partition is {{ic|/dev/sda1}}. A different partition will change every instance of hd0,msdos1. First, find the UUID of the NTFS file system of the Windows's SYSTEM PARTITION where the {{ic|bootmgr}} and its files reside. For example, if Windows {{ic|bootmgr}} exists at {{ic|/media/SYSTEM_RESERVED/bootmgr}}:<br />
<br />
For Windows Vista/7/8/8.1:<br />
<br />
# grub-probe --target=fs_uuid /media/SYSTEM_RESERVED/bootmgr<br />
69B235F6749E84CE<br />
<br />
# grub-probe --target=hints_string /media/SYSTEM_RESERVED/bootmgr<br />
--hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1<br />
<br />
{{Note|For Windows XP, replace {{ic|bootmgr}} with {{ic|NTLDR}} in the above commands. And note that there may not be a separate SYSTEM_RESERVED partition; just probe the file NTLDR on your Windows partition.}}<br />
<br />
Then, add the below code to {{ic|/etc/grub.d/40_custom}} or {{ic|/boot/grub/custom.cfg}} and regenerate {{ic|grub.cfg}} with {{ic|grub-mkconfig}} as explained above to boot Windows (XP, Vista, 7 or 8) installed in BIOS-MBR mode:<br />
<br />
{{Note|These menuentries will work only in Legacy BIOS boot mode. It WILL NOT WORK in uefi installed grub(2). See [[Dual boot with Windows#Windows UEFI vs BIOS limitations]] and [[Dual boot with Windows#Bootloader UEFI vs BIOS limitations]].}}<br />
<br />
For Windows Vista/7/8/8.1:<br />
<br />
if [ "${grub_platform}" == "pc" ]; then<br />
menuentry "Microsoft Windows Vista/7/8/8.1 BIOS-MBR" {<br />
insmod part_msdos<br />
insmod ntfs<br />
insmod search_fs_uuid<br />
insmod ntldr <br />
search --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 69B235F6749E84CE<br />
ntldr /bootmgr<br />
}<br />
fi<br />
<br />
For Windows XP:<br />
<br />
if [ "${grub_platform}" == "pc" ]; then<br />
menuentry "Microsoft Windows XP" {<br />
insmod part_msdos<br />
insmod ntfs<br />
insmod search_fs_uuid<br />
insmod ntldr <br />
search --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 69B235F6749E84CE<br />
ntldr /ntldr<br />
}<br />
fi<br />
<br />
{{Note|In some cases, mine I have installed GRUB before a clean Windows 8, you cannot boot Windows having an error with {{ic|\boot\bcd}} (error code {{ic|0xc000000f}}). You can fix it going to Windows Recovery Console (cmd from install disk) and executing:<br />
x:\> "bootrec.exe /fixboot" <br />
x:\> "bootrec.exe /RebuildBcd".<br />
Do '''not''' use {{ic|bootrec.exe /Fixmbr}} because it will wipe GRUB out.}}<br />
<br />
{{ic|/etc/grub.d/40_custom}} can be used as a template to create {{ic|/etc/grub.d/nn_custom}}. Where {{ic|nn}} defines the precendence, indicating the order the script is executed. The order scripts are executed determine the placement in the grub boot menu.<br />
<br />
{{Note|{{ic|nn}} should be greater than 06 to ensure necessary scripts are executed first.}}<br />
<br />
==== With Windows via EasyBCD and NeoGRUB ====<br />
<br />
{{Merge|NeoGRUB|New page has been created, so this section should be merged there.}}<br />
<br />
Since EasyBCD's NeoGRUB currently does not understand the GRUB menu format, chainload to it by replacing the contents of your {{ic|C:\NST\menu.lst}} file with lines similar to the following:<br />
<br />
default 0<br />
timeout 1<br />
<br />
title Chainload into GRUB v2<br />
root (hd0,7)<br />
kernel /boot/grub/i386-pc/core.img<br />
<br />
Finally, [[#Generate the main configuration file]].<br />
<br />
==== parttool for hide/unhide ====<br />
<br />
If you have a Windows 9x paradigm with hidden {{ic|C:\}} disks GRUB can hide/unhide it using {{ic|parttool}}. For example, to boot the third {{ic|C:\}} disk of three Windows 9x installations on the CLI enter the CLI and:<br />
parttool hd0,1 hidden+ boot-<br />
parttool hd0,2 hidden+ boot-<br />
parttool hd0,3 hidden- boot+<br />
set root=hd0,3<br />
chainloader +1<br />
boot<br />
<br />
=== LVM ===<br />
<br />
If you use [[LVM]] for your {{ic|/boot}}, make sure that the {{ic|lvm}} module is preloaded:<br />
<br />
{{hc|/etc/default/grub|2=<br />
GRUB_PRELOAD_MODULES="lvm"<br />
}}<br />
<br />
=== RAID ===<br />
<br />
GRUB provides convenient handling of RAID volumes. You need to add {{ic|insmod mdraid}} which allows you to address the volume natively. For example, {{ic|/dev/md0}} becomes:<br />
set root=(md/0)<br />
<br />
whereas a partitioned RAID volume (e.g. {{ic|/dev/md0p1}}) becomes:<br />
set root=(md/0,1)<br />
<br />
To install grub when using RAID1 as the {{ic|/boot}} partition (or using {{ic|/boot}} housed on a RAID1 root partition), on devices with GPT ef02/'BIOS boot partition', simply run ''grub-install'' on both of the drives, such as:<br />
# grub-install --target=i386-pc --recheck --debug /dev/sda<br />
# grub-install --target=i386-pc --recheck --debug /dev/sdb<br />
<br />
Where the RAID 1 array housing {{ic|/boot}} is housed on {{ic|/dev/sda}} and {{ic|/dev/sdb}}.<br />
<br />
=== Multiple entries ===<br />
<br />
For tips on managing multiple GRUB entries, for example when using both {{Pkg|linux}} and {{Pkg|linux-lts}} kernels, see [[GRUB/Tips and tricks#Multiple entries]].<br />
<br />
=== Encryption ===<br />
<br />
==== Root partition ====<br />
<br />
For an encrypted root filesystem, it is necessary to edit {{ic|/etc/default/grub}} with the parameters required to unlock the encrypted filesystem during boot. For example, if the [[mkinitcpio]] {{ic|encrypt}} hook is used, the {{ic|cryptdevice}} parameter must be added to {{ic|GRUB_CMDLINE_LINUX<nowiki>=</nowiki>""}} command. In the example below, the {{ic|sda2}} partition has been encrypted as {{ic|/dev/mapper/cryptroot}}:<br />
<br />
{{hc|/etc/default/grub|2=<br />
GRUB_CMDLINE_LINUX="cryptdevice=/dev/sda2:cryptroot"<br />
}}<br />
<br />
Once {{ic|/etc/default/grub}} has been amended, it will then be necessary to [[#Generate the main configuration file]].<br />
<br />
For further information about bootloader configuration for encrypted devices, see [[Dm-crypt/System configuration#Boot loader]].<br />
<br />
{{Tip|If you are upgrading from a working GRUB Legacy configuration, check {{ic|/boot/grub/menu.lst.pacsave}} for the correct device/label to add. Look for them after the text {{ic|kernel /vmlinuz-linux}}.}}<br />
<br />
==== Boot partition ====<br />
<br />
The GRUB [https://www.gnu.org/software/grub/manual/grub.html#Simple-configuration parameter] {{ic|GRUB_ENABLE_CRYPTODISK}} can be used to enable GRUB to ask for a password to open a [[LUKS]] blockdevice in order to read its configuration and load any [[initramfs]] and [[kernel]] from it. This option tries to solve the issue of having an [[Dm-crypt/Specialties#Securing_the_unencrypted_boot_partition|unencrypted boot partition]].<br />
<br />
The feature is enabled by adding: <br />
GRUB_ENABLE_CRYPTODISK=y<br />
to {{ic|/etc/default/grub}}. After this configuration a subsequent run of ''grub-mkconfig'' to [[#Generate the main configuration file]] is required while the encrypted {{ic|/boot}} is mounted. <br />
{{Note|{{ic|1=GRUB_ENABLE_CRYPTODISK=1}} [https://savannah.gnu.org/bugs/?41524 will not work] as opposed to the request shown in GRUB 2.02-beta2.}}<br />
<br />
Depending on the system's setup, note the following: <br />
<br />
* For the feature to work it is not required that {{ic|/boot}} is kept in a separate partition, it may also stay under the system's root {{ic|/}} directory tree.<br />
<br />
* Without further changes you will be prompted twice for a passhrase: the first for GRUB to unlock the {{ic|/boot}} mount point in early boot, the second to unlock the root filesystem itself as described in [[#Root partition]].{{Tip|See [[Dm-crypt/Device encryption#With a keyfile embedded in the initramfs]] for a workaround.}}<br />
<br />
* In order to perform system updates involving the {{ic|/boot}} mount point, it must be ensured that the encrypted {{ic|/boot}} is unlocked to be re-mounted by the initramfs and kernel during boot. With a separate {{ic|/boot}} partition, this may be accomplished by adding an entry to {{ic|/etc/crypttab}} with a keyfile. See [[Dm-crypt/System configuration#crypttab]].<br />
<br />
* If you use a special keymap, a default GRUB installation will not know it. This is relevant for how to enter the passphrase to unlock the LUKS blockdevice.<br />
<br />
* If you experience issues getting the prompt for a password to display (errors regarding cryptouuid, cryptodisk, or "device not found"), try reinstalling grub as below appending the following to the end of your installation command:<br />
<br />
grub-install --target=x86_64-efi --efi-directory=$esp --bootloader-id=grub --recheck '''--modules="part_gpt part_msdos"'''<br />
<br />
== Using the command shell ==<br />
<br />
Since the MBR is too small to store all GRUB modules, only the menu and a few basic commands reside there. The majority of GRUB functionality remains in modules in {{ic|/boot/grub}}, which are inserted as needed. In error conditions (e.g. if the partition layout changes) GRUB may fail to boot. When this happens, a command shell may appear.<br />
<br />
GRUB offers multiple shells/prompts. If there is a problem reading the menu but the bootloader is able to find the disk, you will likely be dropped to the "normal" shell:<br />
grub><br />
<br />
If there is a more serious problem (e.g. GRUB cannot find required files), you may instead be dropped to the "rescue" shell:<br />
grub rescue><br />
<br />
The rescue shell is a restricted subset of the normal shell, offering much less functionality. If dumped to the rescue shell, first try inserting the "normal" module, then starting the "normal" shell:<br />
grub rescue> set prefix=(hdX,Y)/boot/grub<br />
grub rescue> insmod (hdX,Y)/boot/grub/i386-pc/normal.mod<br />
rescue:grub> normal<br />
<br />
=== Pager support ===<br />
<br />
GRUB supports pager for reading commands that provide long output (like the {{ic|help}} command). This works only in normal shell mode and not in rescue mode. To enable pager, in GRUB command shell type:<br />
sh:grub> set pager=1<br />
<br />
=== Using the command shell environment to boot operating systems ===<br />
<br />
grub><br />
<br />
The GRUB's command shell environment can be used to boot operating systems.<br />
A common scenario may be to boot Windows / Linux stored on a drive/partition via '''chainloading'''.<br />
<br />
''Chainloading'' means to load another boot-loader from the current one, ie, chain-loading.<br />
<br />
The other bootloader may be embedded at the starting of the disk(MBR) or at the starting of a partition.<br />
<br />
==== Chainloading a partition ====<br />
<br />
set root=(hdX,Y)<br />
chainloader +1<br />
boot<br />
<br />
X=0,1,2...<br />
Y=1,2,3...<br />
<br />
For example to chainload Windows stored in the first partiton of the first hard disk,<br />
<br />
set root=(hd0,1)<br />
chainloader +1<br />
boot<br />
<br />
Similarly GRUB installed to a partition can be chainloaded.<br />
<br />
==== Chainloading a disk/drive ====<br />
<br />
set root=hdX<br />
chainloader +1<br />
boot<br />
<br />
==== Chainloading Windows/Linux installed in UEFI mode ====<br />
<br />
insmod ntfs<br />
set root=(hd0,gpt4)<br />
chainloader (${root})/EFI/Microsoft/Boot/bootmgfw.efi<br />
boot<br />
<br />
''insmod ntfs'' used for loading the ntfs file system module for loading Windows.<br />
(hd0,gpt4) or /dev/sda4 is my EFI System Partition (ESP).<br />
The entry in the ''chainloader'' line specifies the path of the .efi file to be chain-loaded.<br />
<br />
==== Normal loading ====<br />
<br />
See the examples in [[#Using the rescue console]]<br />
<br />
=== Using the rescue console ===<br />
<br />
See [[#Using the command shell]] first. If unable to activate the standard shell, one possible solution is to boot using a live CD or some other rescue disk to correct configuration errors and reinstall GRUB. However, such a boot disk is not always available (nor necessary); the rescue console is surprisingly robust.<br />
<br />
The available commands in GRUB rescue include {{ic|insmod}}, {{ic|ls}}, {{ic|set}}, and {{ic|unset}}. This example uses {{ic|set}} and {{ic|insmod}}. {{ic|set}} modifies variables and {{ic|insmod}} inserts new modules to add functionality.<br />
<br />
Before starting, the user must know the location of their {{ic|/boot}} partition (be it a separate partition, or a subdirectory under their root):<br />
<br />
grub rescue> set prefix=(hdX,Y)/boot/grub<br />
<br />
where X is the physical drive number and Y is the partition number.<br />
<br />
To expand console capabilities, insert the {{ic|linux}} module:<br />
grub rescue> insmod i386-pc/linux.mod<br />
<br />
{{Note|With a separate boot partition, omit {{ic|/boot}} from the path, (i.e. type {{ic|1=set prefix=(hdX,Y)/grub}}).}}<br />
<br />
This introduces the {{ic|linux}} and {{ic|initrd}} commands, which should be familiar.<br />
<br />
An example, booting Arch Linux:<br />
<br />
set root=(hd0,5)<br />
linux /boot/vmlinuz-linux root=/dev/sda5<br />
initrd /boot/initramfs-linux.img<br />
boot<br />
<br />
With a separate boot partition, again change the lines accordingly:<br />
<br />
set root=(hd0,5)<br />
linux /vmlinuz-linux root=/dev/sda6<br />
initrd /initramfs-linux.img<br />
boot<br />
<br />
{{Note|If you experienced {{ic|error: premature end of file /YOUR_KERNEL_NAME}} during execution of {{ic|linux}} command, you can try {{ic|linux16}} instead.}}<br />
<br />
After successfully booting the Arch Linux installation, users can correct {{ic|grub.cfg}} as needed and then reinstall GRUB.<br />
<br />
To reinstall GRUB and fix the problem completely, changing {{ic|/dev/sda}} if needed. See [[#Installation]] for details.<br />
<br />
== Troubleshooting ==<br />
<br />
=== Intel BIOS not booting GPT ===<br />
<br />
==== MBR ====<br />
<br />
Some Intel BIOS's require at least one bootable MBR partition to be present at boot, causing GPT-partitioned boot setups to be unbootable.<br />
<br />
This can be circumvented by using (for instance) fdisk to mark one of the GPT partitions (preferably the 1007 KiB partition you have created for GRUB already) bootable in the MBR. This can be achieved, using fdisk, by the following commands: Start fdisk against the disk you are installing, for instance {{ic|fdisk /dev/sda}}, then press {{ic|a}} and select the partition you wish to mark as bootable (probably #1) by pressing the corresponding number, finally press {{ic|w}} to write the changes to the MBR.<br />
<br />
{{Note|The bootable-marking must be done in {{ic|fdisk}} or similar, not in GParted or others, as they will not set the bootable flag in the MBR.}}<br />
<br />
With cfdisk, the steps are similar, just {{ic|cfdisk /dev/sda}}, choose bootable (at the left) in the desired hard disk, and quit saving.<br />
<br />
More information is available [http://www.rodsbooks.com/gdisk/bios.html here]<br />
<br />
==== EFI path ====<br />
<br />
Some UEFI firmwares require a bootable file at a known location before they will show UEFI NVRAM boot entries. If this is the case, {{ic|grub-install}} will claim {{ic|efibootmgr}} has added an entry to boot GRUB, however the entry will not show up in the VisualBIOS boot order selector. The solution is to place a file at one of the known locations. Assuming the EFI partition is at {{ic|/boot/efi/}} this will work:<br />
<br />
mkdir /boot/efi/EFI/boot<br />
cp /boot/efi/EFI/grub/grubx64.efi /boot/efi/EFI/boot/bootx64.efi<br />
<br />
This solution worked for an Intel DH87MC motherboard with firmware dated Jan 2014.<br />
<br />
=== Enable debug messages ===<br />
<br />
{{Note|This change is overwritten when [[#Generate the main configuration file]].}}<br />
<br />
Add:<br />
<br />
set pager=1<br />
set debug=all<br />
<br />
to {{ic|grub.cfg}}.<br />
<br />
=== "No suitable mode found" error ===<br />
<br />
If you get this error when booting any menuentry:<br />
<br />
error: no suitable mode found<br />
Booting however<br />
<br />
Then you need to initialize GRUB graphical terminal ({{ic|gfxterm}}) with proper video mode ({{ic|gfxmode}}) in GRUB. This video mode is passed by GRUB to the linux kernel via 'gfxpayload'. In case of UEFI systems, if the GRUB video mode is not initialized, no kernel boot messages will be shown in the terminal (atleast until KMS kicks in).<br />
<br />
Copy {{ic|/usr/share/grub/unicode.pf2}} to ${GRUB_PREFIX_DIR} ({{ic|/boot/grub/}} in case of BIOS and UEFI systems). If GRUB UEFI was installed with {{ic|1=--boot-directory=$esp/EFI}} set, then the directory is {{ic|$esp/EFI/grub/}}:<br />
<br />
# cp /usr/share/grub/unicode.pf2 ${GRUB_PREFIX_DIR}<br />
<br />
If {{ic|/usr/share/grub/unicode.pf2}} does not exist, install {{Pkg|bdf-unifont}}, create the {{ic|unifont.pf2}} file and then copy it to {{ic|${GRUB_PREFIX_DIR<nowiki>}</nowiki>}}:<br />
<br />
# grub-mkfont -o unicode.pf2 /usr/share/fonts/misc/unifont.bdf<br />
<br />
Then, in the {{ic|grub.cfg}} file, add the following lines to enable GRUB to pass the video mode correctly to the kernel, without of which you will only get a black screen (no output) but booting (actually) proceeds successfully without any system hang.<br />
<br />
BIOS systems:<br />
<br />
insmod vbe<br />
<br />
UEFI systems:<br />
<br />
insmod efi_gop<br />
insmod efi_uga<br />
<br />
After that add the following code (common to both BIOS and UEFI):<br />
<br />
insmod font<br />
<br />
if loadfont ${prefix}/fonts/unicode.pf2<br />
then<br />
insmod gfxterm<br />
set gfxmode=auto<br />
set gfxpayload=keep<br />
terminal_output gfxterm<br />
fi<br />
<br />
As you can see for gfxterm (graphical terminal) to function properly, {{ic|unicode.pf2}} font file should exist in {{ic|${GRUB_PREFIX_DIR<nowiki>}</nowiki>}}.<br />
<br />
=== msdos-style error message ===<br />
<br />
grub-setup: warn: This msdos-style partition label has no post-MBR gap; embedding will not be possible!<br />
grub-setup: warn: Embedding is not possible. GRUB can only be installed in this setup by using blocklists.<br />
However, blocklists are UNRELIABLE and its use is discouraged.<br />
grub-setup: error: If you really want blocklists, use --force.<br />
<br />
This error may occur when you try installing GRUB in a VMware container. Read more about it [https://bbs.archlinux.org/viewtopic.php?pid=581760#p581760 here]. It happens when the first partition starts just after the MBR (block 63), without the usual space of 1 MiB (2048 blocks) before the first partition. Read [[#Master Boot Record (MBR) specific instructions]]<br />
<br />
=== UEFI ===<br />
<br />
==== Common installation errors ====<br />
<br />
* If you have a problem when running grub-install with sysfs or procfs and it says you must run {{ic|modprobe efivars}}, try [[Unified Extensible Firmware Interface#Switch to efivarfs]].<br />
* Without {{ic|--target}} or {{ic|--directory}} option, grub-install cannot determine for which firmware to install. In such cases {{ic|grub-install}} will print {{ic|source_dir does not exist. Please specify --target or --directory}}.<br />
* If after running grub-install you are told your partition does not look like an EFI partition then the partition is most likely not {{ic|Fat32}}.<br />
<br />
==== Drop to rescue shell ====<br />
<br />
If GRUB loads but drops you into the rescue shell with no errors, it may be because of a missing or misplaced {{ic|grub.cfg}}. This will happen if GRUB UEFI was installed with {{ic|--boot-directory}} and {{ic|grub.cfg}} is missing OR if the partition number of the boot partition changed (which is hard-coded into the {{ic|grubx64.efi}} file).<br />
<br />
==== GRUB UEFI not loaded ====<br />
<br />
An example of a working EFI:<br />
<br />
{{hc|# efibootmgr -v|<br />
BootCurrent: 0000<br />
Timeout: 3 seconds<br />
BootOrder: 0000,0001,0002<br />
Boot0000* Grub HD(1,800,32000,23532fbb-1bfa-4e46-851a-b494bfe9478c)File(\efi\grub\grub.efi)<br />
Boot0001* Shell HD(1,800,32000,23532fbb-1bfa-4e46-851a-b494bfe9478c)File(\EfiShell.efi)<br />
Boot0002* Festplatte BIOS(2,0,00)P0: SAMSUNG HD204UI<br />
}}<br />
<br />
If the screen only goes black for a second and the next boot option is tried afterwards, according to [https://bbs.archlinux.org/viewtopic.php?pid=981560#p981560 this post], moving GRUB to the partition root can help. The boot option has to be deleted and recreated afterwards. The entry for GRUB should look like this then:<br />
<br />
Boot0000* Grub HD(1,800,32000,23532fbb-1bfa-4e46-851a-b494bfe9478c)File(\grub.efi)<br />
<br />
=== Invalid signature ===<br />
<br />
If trying to boot Windows results in an "invalid signature" error, e.g. after reconfiguring partitions or adding additional hard drives, (re)move GRUB's device configuration and let it reconfigure:<br />
<br />
# mv /boot/grub/device.map /boot/grub/device.map-old<br />
# grub-mkconfig -o /boot/grub/grub.cfg<br />
<br />
{{ic|grub-mkconfig}} should now mention all found boot options, including Windows. If it works, remove {{ic|/boot/grub/device.map-old}}.<br />
<br />
=== Boot freezes ===<br />
<br />
If booting gets stuck without any error message after GRUB loading the kernel and the initial ramdisk, try removing the {{ic|add_efi_memmap}} kernel parameter.<br />
<br />
=== Arch not found from other OS ===<br />
<br />
Some have reported that other distributions have trouble finding Arch Linux automatically with {{ic|os-prober}}. If this problem arises, it has been reported that detection can be improved with the presence of {{ic|/etc/lsb-release}}. This file and updating tool is available with the package {{Pkg|lsb-release}} in the [[official repositories]].<br />
<br />
=== Warning when installing in chroot ===<br />
<br />
When installing GRUB on a LVM system in a chroot environment (e.g. during system installation), you may receive warnings like {{ic|/run/lvm/lvmetad.socket: connect failed: No such file or directory}} or {{ic|WARNING: failed to connect to lvmetad: No such file or directory. Falling back to internal scanning.}} This is because {{ic|/run}} is not available inside the chroot. These warnings will not prevent the system from booting, provided that everything has been done correctly, so you may continue with the installation.<br />
<br />
=== GRUB loads slowly ===<br />
<br />
GRUB can take a long time to load when disk space is low. Check if you have sufficient free disk space on your {{ic|/boot}} or {{ic|/}} partition when you are having problems.<br />
<br />
=== error: unknown filesystem ===<br />
GRUB may output {{ic|error: unknown filesystem}} and refuse to boot for a few reasons. If you are certain that all [[UUID]]s are correct and all filesystems are valid and supported, it may be because your [[#GUID_Partition_Table_.28GPT.29_specific_instructions|BIOS Boot Partition]] is located outside the first 2TB of the drive [https://bbs.archlinux.org/viewtopic.php?id=195948]. Use a partitioning tool of your choice to ensure this partition is located fully within the first 2TB, then reinstall and reconfigure GRUB.<br />
<br />
=== grub-reboot not resetting ===<br />
<br />
GRUB seems to be unable to write to root BTRFS partitions [https://bbs.archlinux.org/viewtopic.php?id=166131]. If you use grub-reboot to boot into another entry it will therefore be unable to update its on-disk environment. Either run grub-reboot from the other entry (for example when switching between various distributions) or consider a different file system. You can reset a "sticky" entry by executing {{ic|grub-editenv create}} and setting {{ic|GRUB_DEFAULT<nowiki>=</nowiki>0}} in your {{ic|/etc/default/grub}} (don't forget {{ic|grub-mkconfig}}).<br />
<br />
=== Old BTRFS prevents installation ===<br />
<br />
If a drive is formatted with BTRFS without creating a partition table (eg. /dev/sdx), then later has partition table written to, there are parts of the BTRFS format that persist. Most utilities and OS's do not see this, but GRUB will refuse to install, even with --force<br />
<br />
# grub-install: warning: Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet..<br />
# grub-install: error: filesystem `btrfs' doesn't support blocklists.<br />
<br />
You can zero the drive, but the easy solution that leaves your data alone is to erase the BTRFS superblock with {{ic|wipefs -o 0x10040 /dev/sdx}}<br />
<br />
== See also ==<br />
<br />
* Official GRUB Manual - https://www.gnu.org/software/grub/manual/grub.html<br />
* Ubuntu wiki page for GRUB - https://help.ubuntu.com/community/Grub2<br />
* GRUB wiki page describing steps to compile for UEFI systems - https://help.ubuntu.com/community/UEFIBooting<br />
* Wikipedia's page on [[Wikipedia:BIOS Boot partition|BIOS Boot partition]]<br />
* http://members.iinet.net/~herman546/p20/GRUB2%20Configuration%20File%20Commands.html - quite complete description of how to configure GRUB</div>Stbinanhttps://wiki.archlinux.org/index.php?title=Ruby_on_Rails&diff=398486Ruby on Rails2015-09-06T09:10:09Z<p>Stbinan: /* Option 2: by systemd */</p>
<hr />
<div>[[Category:Web server]]<br />
[[ja:Ruby on Rails]]<br />
[[zh-CN:Ruby on Rails]]<br />
[http://rubyonrails.org/ Ruby on Rails], often shortened to Rails or RoR, is an open source web application framework for the Ruby programming language. It is intended to be used with an Agile development methodology that is used by web developers for rapid development.<br />
<br />
This document describes how to set up the Ruby on Rails Framework on an Arch Linux system.<br />
<br />
== Installation ==<br />
<br />
Ruby on Rails requires [[Ruby]] to be installed, so read that article first for installation instructions. The {{pkg|nodejs}} package is also required.<br />
<br />
=== RubyGems ===<br />
<br />
{{Note|You can also install Rails system-wide using Gems. To do this, run the following commands as root and append them with {{ic|--no-user-install}}. Please read [[Ruby#Installing gems per-user or system-wide]] for possible dangers of using RubyGem in this way.}}<br />
<br />
The following command will install Rails for the current user:<br />
<br />
$ gem install rails<br />
<br />
Building the documentation takes a while. If you want to skip it, append {{ic|--no-document}} to the install command.<br />
<br />
$ gem install rails --no-document<br />
<br />
gem is a package manager for Ruby modules, somewhat like pacman is to Arch Linux. To update your gems, simply run:<br />
<br />
$ gem update<br />
<br />
=== Pacman ===<br />
<br />
[[Install]] the {{AUR|ruby-rails}} package. Alternatively, see [[Ruby#Managing_RubyGems_using_pacman]].<br />
<br />
=== Quarry binary repository ===<br />
<br />
Install ''ruby-rails'' from the unofficial [[Unofficial user repositories#quarry|quarry]] repository.<br />
<br />
== Configuration ==<br />
<br />
Rails is bundled with a basic HTTP server called WeBrick. You can create a test application to test it. First, create an application with the rails command:<br />
<br />
$ rails new testapp_name<br />
<br />
{{Note|If you get an error like {{ic|Errno::ENOENT: No such file or directory (...) An error occurred while installing x, and Bundler cannot continue.}}, you might have to configure [[Ruby#Bundler|Bundler]] so that it installs gems per-user and not system-wide. Alternatively, run {{ic|# rails new testapp_name}} once as root. If it has completed successfully, delete {{ic|testapp_name/}} and run {{ic|$ rails new testapp_name}} again as a regular user.}}<br />
{{Note|If you get an error message like this:<br />
{{ic|... FetchError: SSL_connect returned&#61;1 errno&#61; 0 state&#61;SSLv2/v3 read server hello A: sslv3 alert handshake<br />
failure <nowiki>(https://s3.amazonaws.com/ production.s3.rubygems.org/gems/rake-10.0.3.gem)</nowiki> }}<br />
install {{Pkg|nodejs}} and try again.}}<br />
<br />
This creates a new folder inside your current working directory. <br />
<br />
$ cd testapp_name<br />
<br />
Next start the web server. It listens on port 3000 by default:<br />
<br />
$ rails server<br />
<br />
Now visit the testapp_name website on your local machine by opening <nowiki>http://localhost:3000</nowiki> in your browser<br />
{{Note|If Ruby complains about not being able to find a JavaScript runtime, install {{Pkg|nodejs}}.}}<br />
<br />
A test-page should shown greeting you "Welcome aboard".<br />
<br />
== Application servers ==<br />
<br />
The built-in Ruby On Rails HTTP server (WeBrick) is convenient for basic development, but it is not recommended for production use. Instead, you should use an application server such as [[#Thin]], [[#Unicorn]] or [[#Apache/Nginx (using Phusion Passenger)|Phusion Passenger]].<br />
<br />
=== Thin ===<br />
<br />
[http://code.macournoyer.com/thin/ Thin] is a fast and very simple Ruby web server.<br />
<br />
First install thin gem:<br />
$ gem install thin<br />
<br />
Then start it using:<br />
$ thin start<br />
<br />
=== Unicorn ===<br />
<br />
Unicorn is an application server that cannot talk directly to clients. Instead, a web server must sit between clients and Unicorn, proxying requests as needed. [http://unicorn.bogomips.org/ Unicorn] is loosely based on Mongrel. It is used by Github, and it uses an architecture that tries hard to find the best child for handling a request. [https://github.com/blog/517-unicorn Explanation of differences between Unicorn and Mongrel].<br />
<br />
Install the Unicorn gem:<br />
# gem install unicorn<br />
<br />
Then create a configuration file for your application in {{ic|/etc/unicorn/}}. For example; here is a configuration example (Based on [http://www.warden.pl/2011/01/07/running-redmine-under-unicorn-in-debian/]) for Redmine:<br />
<br />
{{hc|/etc/unicorn/redmine.ru|<nowiki><br />
working_directory "/srv/http/redmine"<br />
pid "/tmp/redmine.pid"<br />
<br />
preload_app true<br />
timeout 60<br />
worker_processes 4<br />
listen 4000<br />
stderr_path('/var/log/unicorn.log')<br />
<br />
GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true<br />
<br />
after_fork do |server, worker|<br />
#start the worker on port 4000, 4001, 4002 etc...<br />
addr = "0.0.0.0:#{4000 + worker.nr}"<br />
# infinite tries to start the worker<br />
server.listen(addr, :tries => -1, :delay => -1, :backlog => 128)<br />
<br />
#Drop privileges if running as root<br />
worker.user('nobody', 'nobody') if Process.euid == 0<br />
end<br />
</nowiki>}}<br />
<br />
Start it using:<br />
# /usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
==== Systemd service ====<br />
<br />
Put the following contents in {{ic|/etc/systemd/system/unicorn.service}}:<br />
{{hc|/etc/systemd/system/unicorn.service|2=<br />
[Unit]<br />
Description=Unicorn application server<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
User=redmine<br />
ExecStart=/usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
}}<br />
<br />
You can now easily start and stop unicorn using systemctl<br />
<br />
==== Nginx Configuration ====<br />
<br />
After setting up [[Nginx]], configure unicorn as an upstream server using something like this (Warning: this is a stripped example. It probably does not work without additional configuration):<br />
{{bc|1=<br />
http {<br />
upstream unicorn {<br />
server 127.0.0.1:4000 fail_timeout=0;<br />
server 127.0.0.1:4001 fail_timeout=0;<br />
server 127.0.0.1:4002 fail_timeout=0;<br />
server 127.0.0.1:4003 fail_timeout=0;<br />
}<br />
<br />
server {<br />
listen 80 default;<br />
server_name YOURHOSTNAMEHERE;<br />
<br />
location / {<br />
root /srv/http/redmine/public;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
proxy_pass http://unicorn;<br />
}<br />
}<br />
}<br />
}}<br />
<br />
=== Apache/Nginx (using Phusion Passenger) ===<br />
<br />
[http://www.modrails.com/ Passenger] also known as {{ic|mod_rails}} is a module available for [[Nginx]] and [[Apache]], that greatly simplifies setting up a Rails server environment. Nginx does not support modules as Apache and has to be compiled with {{ic|mod_rails}} in order to support Passenger; let Passenger compile it for you. As for Apache, let Passenger set up the module for you.<br />
<br />
Start by installing the 'passenger' gem:<br />
# gem install passenger<br />
<br />
If you are aiming to use [[Apache]], run:<br />
# passenger-install-apache2-module<br />
<br />
In case a rails application is deployed with a sub-URI, like http://example.com/yourapplication, some additional configuration is required, see [http://www.modrails.com/documentation/Users%20guide%20Apache.html#deploying_rails_to_sub_uri the modrails documentation]<br />
<br />
For [[Nginx]]:<br />
# passenger-install-nginx-module<br />
<br />
The installer will provide you with any additional information regarding the installation (such as installing additional libraries).<br />
<br />
To serve an application with Nginx, configure it as follows:<br />
<pre><br />
server {<br />
server_name app.example.org;<br />
root path_to_app/public; # Be sure to point to 'public' folder!<br />
passenger_enabled on;<br />
rails_env development; # Rails environment.<br />
}<br />
</pre><br />
<br />
=== Puma (with Nginx as reverse proxy server) ===<br />
<br />
[http://puma.io/ Puma] ([https://github.com/puma/puma Github Page]) is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications, and is considered the replacement for Webrick and Mongrel. It was designed to be the go-to server for Rubinius, but also works well with JRuby and MRI. While reverse proxy server would acts as a load balancer that routes all external requests to a pool of web apps.<br />
<br />
For a webserver it is better to use a server user and group, check [[Users and groups#Example adding a user]], below use {{ic|rails}} as user name and {{ic|server}} as group name, also {{ic|my_app}} as rails app name.<br />
<br />
Start by copying your app to /var/www/my_app. And set new ownership with<br />
# cd /var/www/<br />
# chown -R rails:server my_app<br />
<br />
and permission for user with<br />
# chmod -R 775 my_app<br />
<br />
Then add {{ic|puma gem}} in the Gemfile and install with<br />
$ cd my_app <br />
$ bundle install<br />
<br />
Also install {{ic|nginx}} by pacman.<br />
<br />
Under your app folder, create sockets, pid and log folder with<br />
$ mkdir -p shared/pids shared/sockets shared/log<br />
<br />
Backup nginx.conf with<br />
# cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup<br />
<br />
Then create a new nginx.conf file with your favorite editor, copy codes below and modify as you like:<br />
<pre><br />
#user html;<br />
worker_processes 1; # this may connect with the worker numbers puma can use.<br />
<br />
#error_log logs/error.log;<br />
#error_log logs/error.log notice;<br />
#error_log logs/error.log info;<br />
<br />
#pid logs/nginx.pid;<br />
<br />
<br />
events {<br />
worker_connections 1024;<br />
}<br />
<br />
http {<br />
upstream app {<br />
# Path to Puma SOCK file, as defined previously<br />
server unix:/var/www/my_app/shared/sockets/puma.sock;<br />
}<br />
<br />
server {<br />
listen 80;<br />
server_name localhost; # or your server name<br />
<br />
root /var/www/my_app/public;<br />
<br />
try_files $uri/index.html $uri @app;<br />
<br />
location @app {<br />
proxy_pass http://app;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
}<br />
<br />
error_page 500 502 503 504 /500.html;<br />
client_max_body_size 4G;<br />
keepalive_timeout 10;<br />
}<br />
}</pre><br />
<br />
Start nginx service with<br />
# systemctl start nginx<br />
<br />
<br />
There are several ways to start puma server, two ways are recommended below:<br />
<br />
In common create file {{ic|config/puma.rb}}, copy codes below and modify as you like:<br />
<pre><br />
# Change to match your CPU core count<br />
# You can check available worker numbers with $ grep -c processor /proc/cpuinfo<br />
# also see the comment in the nginx.conf<br />
workers 2<br />
<br />
# Min and Max threads per worker<br />
#threads 1, 6<br />
<br />
app_dir = File.expand_path("../..", __FILE__)<br />
shared_dir = "#{app_dir}/shared"<br />
<br />
# Default to production<br />
#rails_env = ENV['RAILS_ENV'] || "production"<br />
#environment rails_env<br />
<br />
# Set up socket location<br />
bind "unix://#{shared_dir}/sockets/puma.sock"<br />
<br />
# Logging<br />
#stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true<br />
<br />
# Set master PID and state locations<br />
pidfile "#{shared_dir}/pids/puma.pid"<br />
#state_path "#{shared_dir}/pids/puma.state"<br />
#activate_control_app<br />
<br />
#on_worker_boot do<br />
# require "active_record"<br />
# ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished<br />
# ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])<br />
#end</pre><br />
<br />
==== Option A: With config file ====<br />
<br />
Start server with<br />
$ bundle exec puma -C config/puma.rb<br />
<br />
You can also run it in background with parameter {{ic|-d}} and check with<br />
$ ps aux| grep puma<br />
when you want to {{ic|kill}} it.<br />
<br />
If you want to keep it after you log out, you can use<br />
$ nohup bundle exec puma -C config/puma.rb &<br />
But if the system reboot, the process will still get lost.<br />
<br />
==== Option 2: by systemd ====<br />
<br />
Create a new systemd unit {{ic|puma.service}} under ~/.config/systemd/user/ and copy codes below<br />
<pre><br />
[Unit]<br />
Description=Puma application server<br />
After=network.target<br />
<br />
[Service]<br />
WorkingDirectory=/var/www/my_app<br />
#Environment=RAILS_ENV=production<br />
PIDFile=/var/www/my_app/shared/pids/puma.pid<br />
ExecStart=/home/rails/.gem/ruby/2.2.0/bin/bundle exec \<br />
/home/rails/.gem/ruby/2.2.0/bin/puma \<br />
-C /var/www/my_app/config/puma.rb<br />
<br />
[Install]<br />
WantedBy=default.target</pre><br />
<br />
Hint: For ExecStart, if you've installed gem globally, you can change routes to /usr/local/bin/ in ExecStart.<br />
<br />
Then start puma with<br />
$ systemctl --user start puma<br />
<br />
To enable puma system-widely:<br />
You need to store {{ic|puma.service}} in /etc/systemd/system/ and modify it as below:<br />
<pre><br />
[Unit]<br />
Description=Puma application server<br />
After=network.target<br />
<br />
[Service]<br />
WorkingDirectory=/var/www/my_app<br />
#Environment=RAILS_ENV=production<br />
User=rails<br />
PIDFile=/var/www/my_app/shared/pids/puma.pid<br />
ExecStart=/home/rails/.gem/ruby/2.2.0/bin/bundle exec \<br />
/home/rails/.gem/ruby/2.2.0/bin/puma \<br />
-C /var/www/my_app/config/puma.rb<br />
<br />
[Install]<br />
WantedBy=multi-user.target</pre><br />
<br />
<br />
For further reading take a look at [[#References]]. Also, for easily deploying app in production mode, you can try [https://github.com/capistrano/capistrano capistrano]<br />
<br />
== Databases ==<br />
<br />
Most web applications will need to interact with some sort of database. ActiveRecord (the ORM used by Rails to provide database abstraction) supports several database vendors, the most popular of which are MySQL, SQLite, and PostgreSQL.<br />
<br />
=== SQLite ===<br />
<br />
SQLite is the default lightweight database for Ruby on Rails. To enable SQLite, simply install {{Pkg|sqlite}}.<br />
<br />
=== PostgreSQL ===<br />
<br />
Install {{Pkg|postgresql}}.<br />
<br />
=== MySQL ===<br />
<br />
First, install and configure a MySQL server. Please refer to [[MySQL]] on how to do this.<br />
<br />
A gem with some native extensions is required, probably best installed as root:<br />
# gem install mysql<br />
<br />
You can generate a rails application configured for MySQL by using the {{ic|-d}} parameter:<br />
$ rails new testapp_name -d mysql<br />
<br />
You then need to edit {{ic|config/database.yml}}. Rails uses different databases for development, testing, production and other environments. Here is an example development configuration for MySQL running on localhost:<br />
<br />
development:<br />
adapter: mysql<br />
database: my_application_database<br />
username: development<br />
password: my_secret_password<br />
<br />
Note that you do not have to actually create the database using MySQL, as this can be done via Rails with:<br />
# rake db:create<br />
<br />
If no errors are shown, then your database has been created and Rails can talk to your MySQL database.<br />
<br />
== The Perfect Rails Setup ==<br />
<br />
''Phusion Passenger running multiple Ruby versions.''<br />
<br />
* [https://www.archlinux.org/ Arch Linux]: A simple, lightweight distribution. ;)<br />
* [http://www.nginx.org/ Nginx]: A fast and lightweight '''web server''' with a strong focus on high concurrency, performance and low memory usage.<br />
* [http://www.modrails.com/ Passenger] (a.k.a. mod_rails or mod_rack): Supports both Apache and Nginx web servers. It makes deployment of Ruby web applications, such as those built on Ruby on Rails web framework, a breeze.<br />
* [https://rvm.io/ Ruby Version Manager] (RVM): A command-line tool which allows you to easily install, manage, and work with multiple Ruby environments from interpreters to sets of gems. RVM lets you deploy each project with its own completely self-contained and dedicated environment —from the specific version of ruby, all the way down to the precise set of required gems to run your application—.<br />
* [http://sqlite.org/ SQLite]: The default lightweight '''database''' for Ruby on Rails.<br />
<br />
=== Step 0: SQLite ===<br />
<br />
Install {{Pkg|sqlite}}.<br />
<br />
{{note|Of course SQLite is not critical in this setup, you can use MySQL and PostgreSQL as well.}}<br />
<br />
=== Step 1: RVM ===<br />
<br />
Make a multi-user [[RVM]] installation as specified [[RVM#Multi-user_installation|here]].<br />
<br />
In the 'adding users to the rvm group' step, do<br />
# usermod -a -G rvm http<br />
# usermod -a -G rvm nobody<br />
<br />
{{ic|http}} and {{ic|nobody}} are the users related to Nginx and Passenger, respectively.<br />
<br />
{{note|Maybe adding the 'nobody' user to the 'rvm' group is not necessary.}}<br />
<br />
=== Step 2: Rubies ===<br />
<br />
Once you have a working RVM installation in your hands, it is time to install the latest Ruby interpreter<br />
{{Note|During the installation of Ruby patches will be applied. Consider installing the {{ic|base-devel}} group beforehand.}}<br />
<br />
$ rvm install 2.0.0<br />
<br />
{{Note| It may be useful to delete the 'global' gemsets of the environments that have web applications. Their gems might somehow interfere with Passenger. In that case, a {{ic|rvm 2.0.0 do gemset delete global}} is sufficient.}}<br />
<br />
=== Step 3: Nginx with Passenger support ===<br />
<br />
Run the following to allow passenger install nginx:<br />
$ rvm use 2.0.0 <br />
$ gem install passenger<br />
$ rvmsudo passenger-install-nginx-module<br />
<br />
The passenger gem will be put into the ''default'' gemset.<br />
<br />
This will download the sources of Nginx, compile and install it for you. It will guide you through all the process. Note that the default location for Nginx will be {{ic|/opt/nginx}}.<br />
<br />
{{Note|If you encounter a compilation error regarding Boost threads, see [https://bbs.archlinux.org/viewtopic.php?id&#61;139164 this] article.}}<br />
<br />
After completion, add the following two lines into the 'http block' at {{ic|/opt/nginx/conf/nginx.conf}} that look like:<br />
<br />
http { <br />
...<br />
passenger_root /usr/local/rvm/gems/ruby-2.0.0-p353/gems/passenger-3.0.9;<br />
passenger_ruby /usr/local/rvm/wrappers/ruby-2.0.0-p353/ruby;<br />
...<br />
}<br />
<br />
{{Note|This step is currently being done automatically by the installer script.}}<br />
<br />
=== Step 4: Gemsets and Apps ===<br />
<br />
For each Rails application you should have a gemset. Suppose that you want to try [http://refinerycms.com RefineryCMS] against [http://www.browsercms.org BrowserCMS], two open-source Content Management Systems based on Rails.<br />
<br />
Install RefineryCMS first:<br />
<br />
$ rvm use 2.0.0@refinery --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install refinerycms refinerycms-i18n sqlite3<br />
<br />
Deploy a RefineryCMS instance called ''refineria'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo refinerycms refineria<br />
<br />
Install BrowserCMS in a different gemset:<br />
<br />
$ rvm use 2.0.0@browser --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install browsercms sqlite3<br />
<br />
Deploy a BrowserCMS instance called ''navegador'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo browsercms demo navegador<br />
$ cd /srv/http/navegador<br />
$ rvmsudo rake db:install<br />
<br />
=== Passenger for Nginx and Passenger Standalone ===<br />
<br />
Observe that the passenger gem was installed three times and with different intentions; in the environments<br />
* ''2.0.0'' => for Nginx,<br />
* ''2.0.0@refinery'' => Standalone<br />
* ''2.0.0@browser'' => Standalone<br />
<br />
The strategy is to combine Passenger for Nginx with Passenger Standalone. One must first identify the Ruby environment (interpreter plus gemset) that one uses the most; in this setup the Ruby interpreter and the default gemset were selected. One then proceeds with setting up Passenger for Nginx to use that environment (step 3).<br />
* Applications within the chosen environment can be served as in [[#Apache.2FNginx .28using Phusion Passenger.29|Apache/Nginx (using Phusion Passenger)]], page up in this article.<br />
* All applications that are to use a different Ruby version and/or gemset can be served separately through Passenger Standalone and hook into the main web server via a reverse proxy configuration (step 6).<br />
<br />
=== Step 5: .rvmrc files and ownerships ===<br />
<br />
This step is crucial for the correct behaviour of the setup. RVM seeks for .rvmrc files when changing folders; if it finds one, it reads it. In these files normally one stores a line like<br />
rvm <ruby_version>@<gemset_name><br />
so the specified environment is set at the entrance of applications' root folder.<br />
<br />
Create /srv/http/refineria/.rvmrc doing<br />
# echo "rvm ree@refinery" > /srv/http/refineria/.rvmrc<br />
, and /srv/http/navegador/.rvmrc with<br />
# echo "rvm 2.0.0@browser" > /srv/http/navegador/.rvmrc<br />
You have to enter to both application root folders now, because every first time that RVM finds a .rvmrc it asks you if you trust the given file, consequently you must validate the two files you have just created.<br />
<br />
These files aid the programs involved to find the correct gems.<br />
<br />
Apart, if applications' files and folders are not owned by the right user you will face database write-access problems. The use of rvmsudo produces ''root''-owned archives when generated by Rails; in the other hand, ''nobody'' is the user for Passenger —if you have not changed it—: who will use and should posses them. Fix this doing<br />
# chown -R nobody.nobody /srv/http/refineria /srv/http/navegador<br />
<br />
=== Step 6: Reverse proxies ===<br />
<br />
You have to start the Passenger Standalone web servers for your applications. So, do<br />
$ cd /srv/http/refineria<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
and<br />
$ cd /srv/http/navegador<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
. The first time that you run a Passenger Standalone it will perform a minor installation.<br />
<br />
Note that you are using ''unix domain'' sockets instead of the commonly-used ''TCP'' sockets; it turns out that unix domain are significantly faster than TCP sockets.<br />
<br />
{{note|If you are experimenting trouble with unix sockets, changing to TCP should work:<br />
rvmsudo passenger start -a 127.0.0.1 -p 3000 -d<br />
}}<br />
<br />
==== Launch Passenger Standalone daemons at system start-up ====<br />
<br />
''Do you have a script? Please post it here.''<br />
<br />
The systemd script below was made for a Typo blog I host at /srv/http/typo. It is located at /etc/systemd/system/passenger_typo.service. I set the Environment= tags (see "man systemd.exec") from the output of "rvm env". The only exception was PATH=, which I had to combine from my regular PATH and the output of rvm env.<br />
<br />
Note: If you do not set the "WorkingDirectory=" variable to your application folder, passenger will fail to find your app and will subsequently shut itself down.<br />
<br />
<pre><br />
[Unit]<br />
Description=Passenger Standalone Script for Typo<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
WorkingDirectory=/srv/http/typo<br />
PIDFile=/srv/http/typo/tmp/pids/passenger.pid<br />
<br />
Environment=PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo/bin:/usr/local/rvm/gems/ruby-2.0.0-p0@global/bin:/usr/local/rvm/rubies/ruby-2.0.0-p0/bin:/usr/local/rvm/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/bin/core_perl<br />
Environment=rvm_env_string=ruby-2.0.0-p0@typo<br />
Environment=rvm_path=/usr/local/rvm<br />
Environment=rvm_ruby_string=ruby-2.0.0-p0<br />
Environment=rvm_gemset_name=typo<br />
Environment=RUBY_VERSION=ruby-2.0.0-p0<br />
Environment=GEM_HOME=/usr/local/rvm/gems/ruby-2.0.0-p0@typo<br />
Environment=GEM_PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo:/usr/local/rvm/gems/ruby-2.0.0-p0@global<br />
Environment=MY_RUBY_HOME=/usr/local/rvm/rubies/ruby-2.0.0-p0<br />
Environment=IRBRC=/usr/local/rvm/rubies/ruby-2.0.0-p0/.irbrc<br />
<br />
ExecStart=/bin/bash -c "rvmsudo passenger start --socket /srv/http/typo/tmp/sockets/passenger.socket -d"<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
</pre><br />
<br />
=== Step 7: Deployment ===<br />
<br />
==== With subdomains ====<br />
<br />
Once again edit /opt/nginx/conf/nginx.conf to include some vital instructions:<br />
<br />
<pre><br />
## RefineryCMS ##<br />
<br />
server {<br />
server_name refinery.domain.com;<br />
root /srv/http/refineria/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/refineria/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
<br />
## BrowserCMS ##<br />
<br />
server {<br />
server_name browser.domain.com;<br />
root /srv/http/navegador/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/navegador/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
{{note|Or if using TCP sockets, configure the ''proxy_pass'' directive like<br />
<pre>proxy_pass http://127.0.0.1:3000;</pre><br />
}}<br />
<br />
==== Without subdomains ====<br />
<br />
If you for some reason do not want to host each application on its own subdomain but rather in a url like: {{ic|site.com/railsapp}} then you could do something like this in your config:<br />
<br />
<pre><br />
server {<br />
server_name site.com;<br />
#Base for the html files etc<br />
root /srv/http/;<br />
<br />
#First application you want hosted under domain site.com/railsapp<br />
location /railsapp {<br />
root /srv/http/railsapp/public;<br />
#you may need to change passenger_base_uri to be the uri you want to point at, ie:<br />
#passenger_base_uri /railsapp;<br />
#but probably only if you are using the other solution with passenger phusion<br />
proxy_pass http://unix:/srv/http/railsapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
<br />
#Second applicatino you want hosted under domain site.com/anotherapp<br />
location /anotherapp {<br />
root /srv/http/anotherapp/public;<br />
#same thing about the passenger_base_uri here, but with value /anotherapp instead<br />
proxy_pass http://unix:/srv/http/anotherapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
At this point you are in conditions to run Nginx with:<br />
<br />
# systemctl start nginx<br />
<br />
and to access both CMSs through ''refinery.domain.com'' and ''browser.domain.com''.<br />
<br />
=== References ===<br />
<br />
* http://beginrescueend.com/integration/passenger<br />
* http://blog.phusion.nl/2010/09/21/phusion-passenger-running-multiple-ruby-versions<br />
* http://www.ruby-journal.com/how-to-setup-rails-app-with-puma-and-nginx/<br />
* https://www.digitalocean.com/community/tutorials/how-to-deploy-a-rails-app-with-puma-and-nginx-on-ubuntu-14-04<br />
<br />
== See also ==<br />
<br />
* [[Ruby]]<br />
* [[Nginx]]<br />
* [[LAMP]]<br />
* [[MySQL]]<br />
<br />
== References ==<br />
<br />
* Ruby on Rails http://rubyonrails.org/download.<br />
* Mongrel http://mongrel.rubyforge.org.</div>Stbinanhttps://wiki.archlinux.org/index.php?title=Ruby_on_Rails&diff=398485Ruby on Rails2015-09-06T09:05:06Z<p>Stbinan: /* Option A: With config file */</p>
<hr />
<div>[[Category:Web server]]<br />
[[ja:Ruby on Rails]]<br />
[[zh-CN:Ruby on Rails]]<br />
[http://rubyonrails.org/ Ruby on Rails], often shortened to Rails or RoR, is an open source web application framework for the Ruby programming language. It is intended to be used with an Agile development methodology that is used by web developers for rapid development.<br />
<br />
This document describes how to set up the Ruby on Rails Framework on an Arch Linux system.<br />
<br />
== Installation ==<br />
<br />
Ruby on Rails requires [[Ruby]] to be installed, so read that article first for installation instructions. The {{pkg|nodejs}} package is also required.<br />
<br />
=== RubyGems ===<br />
<br />
{{Note|You can also install Rails system-wide using Gems. To do this, run the following commands as root and append them with {{ic|--no-user-install}}. Please read [[Ruby#Installing gems per-user or system-wide]] for possible dangers of using RubyGem in this way.}}<br />
<br />
The following command will install Rails for the current user:<br />
<br />
$ gem install rails<br />
<br />
Building the documentation takes a while. If you want to skip it, append {{ic|--no-document}} to the install command.<br />
<br />
$ gem install rails --no-document<br />
<br />
gem is a package manager for Ruby modules, somewhat like pacman is to Arch Linux. To update your gems, simply run:<br />
<br />
$ gem update<br />
<br />
=== Pacman ===<br />
<br />
[[Install]] the {{AUR|ruby-rails}} package. Alternatively, see [[Ruby#Managing_RubyGems_using_pacman]].<br />
<br />
=== Quarry binary repository ===<br />
<br />
Install ''ruby-rails'' from the unofficial [[Unofficial user repositories#quarry|quarry]] repository.<br />
<br />
== Configuration ==<br />
<br />
Rails is bundled with a basic HTTP server called WeBrick. You can create a test application to test it. First, create an application with the rails command:<br />
<br />
$ rails new testapp_name<br />
<br />
{{Note|If you get an error like {{ic|Errno::ENOENT: No such file or directory (...) An error occurred while installing x, and Bundler cannot continue.}}, you might have to configure [[Ruby#Bundler|Bundler]] so that it installs gems per-user and not system-wide. Alternatively, run {{ic|# rails new testapp_name}} once as root. If it has completed successfully, delete {{ic|testapp_name/}} and run {{ic|$ rails new testapp_name}} again as a regular user.}}<br />
{{Note|If you get an error message like this:<br />
{{ic|... FetchError: SSL_connect returned&#61;1 errno&#61; 0 state&#61;SSLv2/v3 read server hello A: sslv3 alert handshake<br />
failure <nowiki>(https://s3.amazonaws.com/ production.s3.rubygems.org/gems/rake-10.0.3.gem)</nowiki> }}<br />
install {{Pkg|nodejs}} and try again.}}<br />
<br />
This creates a new folder inside your current working directory. <br />
<br />
$ cd testapp_name<br />
<br />
Next start the web server. It listens on port 3000 by default:<br />
<br />
$ rails server<br />
<br />
Now visit the testapp_name website on your local machine by opening <nowiki>http://localhost:3000</nowiki> in your browser<br />
{{Note|If Ruby complains about not being able to find a JavaScript runtime, install {{Pkg|nodejs}}.}}<br />
<br />
A test-page should shown greeting you "Welcome aboard".<br />
<br />
== Application servers ==<br />
<br />
The built-in Ruby On Rails HTTP server (WeBrick) is convenient for basic development, but it is not recommended for production use. Instead, you should use an application server such as [[#Thin]], [[#Unicorn]] or [[#Apache/Nginx (using Phusion Passenger)|Phusion Passenger]].<br />
<br />
=== Thin ===<br />
<br />
[http://code.macournoyer.com/thin/ Thin] is a fast and very simple Ruby web server.<br />
<br />
First install thin gem:<br />
$ gem install thin<br />
<br />
Then start it using:<br />
$ thin start<br />
<br />
=== Unicorn ===<br />
<br />
Unicorn is an application server that cannot talk directly to clients. Instead, a web server must sit between clients and Unicorn, proxying requests as needed. [http://unicorn.bogomips.org/ Unicorn] is loosely based on Mongrel. It is used by Github, and it uses an architecture that tries hard to find the best child for handling a request. [https://github.com/blog/517-unicorn Explanation of differences between Unicorn and Mongrel].<br />
<br />
Install the Unicorn gem:<br />
# gem install unicorn<br />
<br />
Then create a configuration file for your application in {{ic|/etc/unicorn/}}. For example; here is a configuration example (Based on [http://www.warden.pl/2011/01/07/running-redmine-under-unicorn-in-debian/]) for Redmine:<br />
<br />
{{hc|/etc/unicorn/redmine.ru|<nowiki><br />
working_directory "/srv/http/redmine"<br />
pid "/tmp/redmine.pid"<br />
<br />
preload_app true<br />
timeout 60<br />
worker_processes 4<br />
listen 4000<br />
stderr_path('/var/log/unicorn.log')<br />
<br />
GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true<br />
<br />
after_fork do |server, worker|<br />
#start the worker on port 4000, 4001, 4002 etc...<br />
addr = "0.0.0.0:#{4000 + worker.nr}"<br />
# infinite tries to start the worker<br />
server.listen(addr, :tries => -1, :delay => -1, :backlog => 128)<br />
<br />
#Drop privileges if running as root<br />
worker.user('nobody', 'nobody') if Process.euid == 0<br />
end<br />
</nowiki>}}<br />
<br />
Start it using:<br />
# /usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
==== Systemd service ====<br />
<br />
Put the following contents in {{ic|/etc/systemd/system/unicorn.service}}:<br />
{{hc|/etc/systemd/system/unicorn.service|2=<br />
[Unit]<br />
Description=Unicorn application server<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
User=redmine<br />
ExecStart=/usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
}}<br />
<br />
You can now easily start and stop unicorn using systemctl<br />
<br />
==== Nginx Configuration ====<br />
<br />
After setting up [[Nginx]], configure unicorn as an upstream server using something like this (Warning: this is a stripped example. It probably does not work without additional configuration):<br />
{{bc|1=<br />
http {<br />
upstream unicorn {<br />
server 127.0.0.1:4000 fail_timeout=0;<br />
server 127.0.0.1:4001 fail_timeout=0;<br />
server 127.0.0.1:4002 fail_timeout=0;<br />
server 127.0.0.1:4003 fail_timeout=0;<br />
}<br />
<br />
server {<br />
listen 80 default;<br />
server_name YOURHOSTNAMEHERE;<br />
<br />
location / {<br />
root /srv/http/redmine/public;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
proxy_pass http://unicorn;<br />
}<br />
}<br />
}<br />
}}<br />
<br />
=== Apache/Nginx (using Phusion Passenger) ===<br />
<br />
[http://www.modrails.com/ Passenger] also known as {{ic|mod_rails}} is a module available for [[Nginx]] and [[Apache]], that greatly simplifies setting up a Rails server environment. Nginx does not support modules as Apache and has to be compiled with {{ic|mod_rails}} in order to support Passenger; let Passenger compile it for you. As for Apache, let Passenger set up the module for you.<br />
<br />
Start by installing the 'passenger' gem:<br />
# gem install passenger<br />
<br />
If you are aiming to use [[Apache]], run:<br />
# passenger-install-apache2-module<br />
<br />
In case a rails application is deployed with a sub-URI, like http://example.com/yourapplication, some additional configuration is required, see [http://www.modrails.com/documentation/Users%20guide%20Apache.html#deploying_rails_to_sub_uri the modrails documentation]<br />
<br />
For [[Nginx]]:<br />
# passenger-install-nginx-module<br />
<br />
The installer will provide you with any additional information regarding the installation (such as installing additional libraries).<br />
<br />
To serve an application with Nginx, configure it as follows:<br />
<pre><br />
server {<br />
server_name app.example.org;<br />
root path_to_app/public; # Be sure to point to 'public' folder!<br />
passenger_enabled on;<br />
rails_env development; # Rails environment.<br />
}<br />
</pre><br />
<br />
=== Puma (with Nginx as reverse proxy server) ===<br />
<br />
[http://puma.io/ Puma] ([https://github.com/puma/puma Github Page]) is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications, and is considered the replacement for Webrick and Mongrel. It was designed to be the go-to server for Rubinius, but also works well with JRuby and MRI. While reverse proxy server would acts as a load balancer that routes all external requests to a pool of web apps.<br />
<br />
For a webserver it is better to use a server user and group, check [[Users and groups#Example adding a user]], below use {{ic|rails}} as user name and {{ic|server}} as group name, also {{ic|my_app}} as rails app name.<br />
<br />
Start by copying your app to /var/www/my_app. And set new ownership with<br />
# cd /var/www/<br />
# chown -R rails:server my_app<br />
<br />
and permission for user with<br />
# chmod -R 775 my_app<br />
<br />
Then add {{ic|puma gem}} in the Gemfile and install with<br />
$ cd my_app <br />
$ bundle install<br />
<br />
Also install {{ic|nginx}} by pacman.<br />
<br />
Under your app folder, create sockets, pid and log folder with<br />
$ mkdir -p shared/pids shared/sockets shared/log<br />
<br />
Backup nginx.conf with<br />
# cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup<br />
<br />
Then create a new nginx.conf file with your favorite editor, copy codes below and modify as you like:<br />
<pre><br />
#user html;<br />
worker_processes 1; # this may connect with the worker numbers puma can use.<br />
<br />
#error_log logs/error.log;<br />
#error_log logs/error.log notice;<br />
#error_log logs/error.log info;<br />
<br />
#pid logs/nginx.pid;<br />
<br />
<br />
events {<br />
worker_connections 1024;<br />
}<br />
<br />
http {<br />
upstream app {<br />
# Path to Puma SOCK file, as defined previously<br />
server unix:/var/www/my_app/shared/sockets/puma.sock;<br />
}<br />
<br />
server {<br />
listen 80;<br />
server_name localhost; # or your server name<br />
<br />
root /var/www/my_app/public;<br />
<br />
try_files $uri/index.html $uri @app;<br />
<br />
location @app {<br />
proxy_pass http://app;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
}<br />
<br />
error_page 500 502 503 504 /500.html;<br />
client_max_body_size 4G;<br />
keepalive_timeout 10;<br />
}<br />
}</pre><br />
<br />
Start nginx service with<br />
# systemctl start nginx<br />
<br />
<br />
There are several ways to start puma server, two ways are recommended below:<br />
<br />
In common create file {{ic|config/puma.rb}}, copy codes below and modify as you like:<br />
<pre><br />
# Change to match your CPU core count<br />
# You can check available worker numbers with $ grep -c processor /proc/cpuinfo<br />
# also see the comment in the nginx.conf<br />
workers 2<br />
<br />
# Min and Max threads per worker<br />
#threads 1, 6<br />
<br />
app_dir = File.expand_path("../..", __FILE__)<br />
shared_dir = "#{app_dir}/shared"<br />
<br />
# Default to production<br />
#rails_env = ENV['RAILS_ENV'] || "production"<br />
#environment rails_env<br />
<br />
# Set up socket location<br />
bind "unix://#{shared_dir}/sockets/puma.sock"<br />
<br />
# Logging<br />
#stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true<br />
<br />
# Set master PID and state locations<br />
pidfile "#{shared_dir}/pids/puma.pid"<br />
#state_path "#{shared_dir}/pids/puma.state"<br />
#activate_control_app<br />
<br />
#on_worker_boot do<br />
# require "active_record"<br />
# ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished<br />
# ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])<br />
#end</pre><br />
<br />
==== Option A: With config file ====<br />
<br />
Start server with<br />
$ bundle exec puma -C config/puma.rb<br />
<br />
You can also run it in background with parameter {{ic|-d}} and check with<br />
$ ps aux| grep puma<br />
when you want to {{ic|kill}} it.<br />
<br />
If you want to keep it after you log out, you can use<br />
$ nohup bundle exec puma -C config/puma.rb &<br />
But if the system reboot, the process will still get lost.<br />
<br />
==== Option 2: by systemd ====<br />
<br />
Create a new systemd unit {{ic|puma.service}} under ~/.config/systemd/user/ and copy codes below<br />
<pre><br />
[Unit]<br />
Description=Puma application server<br />
After=network.target<br />
<br />
[Service]<br />
WorkingDirectory=/var/www/my_app<br />
#Environment=RAILS_ENV=production<br />
#User=rails<br />
PIDFile=/var/www/my_app/shared/pids/puma.pid<br />
ExecStart=/home/rails/.gem/ruby/2.2.0/bin/bundle exec \<br />
/home/rails/.gem/ruby/2.2.0/bin/puma \<br />
-C /var/www/my_app/config/puma.rb<br />
<br />
[Install]<br />
WantedBy=multi-user.target</pre><br />
<br />
Hint: For ExecStart, if you've installed gem globally, you can change routes to /usr/local/bin/ in ExecStart.<br />
<br />
Then start puma with<br />
$ systemctl --user start puma<br />
<br />
For further reading take a look at [[#References]]. Also, for easily deploying app in production mode, you can try [https://github.com/capistrano/capistrano capistrano]<br />
<br />
== Databases ==<br />
<br />
Most web applications will need to interact with some sort of database. ActiveRecord (the ORM used by Rails to provide database abstraction) supports several database vendors, the most popular of which are MySQL, SQLite, and PostgreSQL.<br />
<br />
=== SQLite ===<br />
<br />
SQLite is the default lightweight database for Ruby on Rails. To enable SQLite, simply install {{Pkg|sqlite}}.<br />
<br />
=== PostgreSQL ===<br />
<br />
Install {{Pkg|postgresql}}.<br />
<br />
=== MySQL ===<br />
<br />
First, install and configure a MySQL server. Please refer to [[MySQL]] on how to do this.<br />
<br />
A gem with some native extensions is required, probably best installed as root:<br />
# gem install mysql<br />
<br />
You can generate a rails application configured for MySQL by using the {{ic|-d}} parameter:<br />
$ rails new testapp_name -d mysql<br />
<br />
You then need to edit {{ic|config/database.yml}}. Rails uses different databases for development, testing, production and other environments. Here is an example development configuration for MySQL running on localhost:<br />
<br />
development:<br />
adapter: mysql<br />
database: my_application_database<br />
username: development<br />
password: my_secret_password<br />
<br />
Note that you do not have to actually create the database using MySQL, as this can be done via Rails with:<br />
# rake db:create<br />
<br />
If no errors are shown, then your database has been created and Rails can talk to your MySQL database.<br />
<br />
== The Perfect Rails Setup ==<br />
<br />
''Phusion Passenger running multiple Ruby versions.''<br />
<br />
* [https://www.archlinux.org/ Arch Linux]: A simple, lightweight distribution. ;)<br />
* [http://www.nginx.org/ Nginx]: A fast and lightweight '''web server''' with a strong focus on high concurrency, performance and low memory usage.<br />
* [http://www.modrails.com/ Passenger] (a.k.a. mod_rails or mod_rack): Supports both Apache and Nginx web servers. It makes deployment of Ruby web applications, such as those built on Ruby on Rails web framework, a breeze.<br />
* [https://rvm.io/ Ruby Version Manager] (RVM): A command-line tool which allows you to easily install, manage, and work with multiple Ruby environments from interpreters to sets of gems. RVM lets you deploy each project with its own completely self-contained and dedicated environment —from the specific version of ruby, all the way down to the precise set of required gems to run your application—.<br />
* [http://sqlite.org/ SQLite]: The default lightweight '''database''' for Ruby on Rails.<br />
<br />
=== Step 0: SQLite ===<br />
<br />
Install {{Pkg|sqlite}}.<br />
<br />
{{note|Of course SQLite is not critical in this setup, you can use MySQL and PostgreSQL as well.}}<br />
<br />
=== Step 1: RVM ===<br />
<br />
Make a multi-user [[RVM]] installation as specified [[RVM#Multi-user_installation|here]].<br />
<br />
In the 'adding users to the rvm group' step, do<br />
# usermod -a -G rvm http<br />
# usermod -a -G rvm nobody<br />
<br />
{{ic|http}} and {{ic|nobody}} are the users related to Nginx and Passenger, respectively.<br />
<br />
{{note|Maybe adding the 'nobody' user to the 'rvm' group is not necessary.}}<br />
<br />
=== Step 2: Rubies ===<br />
<br />
Once you have a working RVM installation in your hands, it is time to install the latest Ruby interpreter<br />
{{Note|During the installation of Ruby patches will be applied. Consider installing the {{ic|base-devel}} group beforehand.}}<br />
<br />
$ rvm install 2.0.0<br />
<br />
{{Note| It may be useful to delete the 'global' gemsets of the environments that have web applications. Their gems might somehow interfere with Passenger. In that case, a {{ic|rvm 2.0.0 do gemset delete global}} is sufficient.}}<br />
<br />
=== Step 3: Nginx with Passenger support ===<br />
<br />
Run the following to allow passenger install nginx:<br />
$ rvm use 2.0.0 <br />
$ gem install passenger<br />
$ rvmsudo passenger-install-nginx-module<br />
<br />
The passenger gem will be put into the ''default'' gemset.<br />
<br />
This will download the sources of Nginx, compile and install it for you. It will guide you through all the process. Note that the default location for Nginx will be {{ic|/opt/nginx}}.<br />
<br />
{{Note|If you encounter a compilation error regarding Boost threads, see [https://bbs.archlinux.org/viewtopic.php?id&#61;139164 this] article.}}<br />
<br />
After completion, add the following two lines into the 'http block' at {{ic|/opt/nginx/conf/nginx.conf}} that look like:<br />
<br />
http { <br />
...<br />
passenger_root /usr/local/rvm/gems/ruby-2.0.0-p353/gems/passenger-3.0.9;<br />
passenger_ruby /usr/local/rvm/wrappers/ruby-2.0.0-p353/ruby;<br />
...<br />
}<br />
<br />
{{Note|This step is currently being done automatically by the installer script.}}<br />
<br />
=== Step 4: Gemsets and Apps ===<br />
<br />
For each Rails application you should have a gemset. Suppose that you want to try [http://refinerycms.com RefineryCMS] against [http://www.browsercms.org BrowserCMS], two open-source Content Management Systems based on Rails.<br />
<br />
Install RefineryCMS first:<br />
<br />
$ rvm use 2.0.0@refinery --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install refinerycms refinerycms-i18n sqlite3<br />
<br />
Deploy a RefineryCMS instance called ''refineria'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo refinerycms refineria<br />
<br />
Install BrowserCMS in a different gemset:<br />
<br />
$ rvm use 2.0.0@browser --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install browsercms sqlite3<br />
<br />
Deploy a BrowserCMS instance called ''navegador'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo browsercms demo navegador<br />
$ cd /srv/http/navegador<br />
$ rvmsudo rake db:install<br />
<br />
=== Passenger for Nginx and Passenger Standalone ===<br />
<br />
Observe that the passenger gem was installed three times and with different intentions; in the environments<br />
* ''2.0.0'' => for Nginx,<br />
* ''2.0.0@refinery'' => Standalone<br />
* ''2.0.0@browser'' => Standalone<br />
<br />
The strategy is to combine Passenger for Nginx with Passenger Standalone. One must first identify the Ruby environment (interpreter plus gemset) that one uses the most; in this setup the Ruby interpreter and the default gemset were selected. One then proceeds with setting up Passenger for Nginx to use that environment (step 3).<br />
* Applications within the chosen environment can be served as in [[#Apache.2FNginx .28using Phusion Passenger.29|Apache/Nginx (using Phusion Passenger)]], page up in this article.<br />
* All applications that are to use a different Ruby version and/or gemset can be served separately through Passenger Standalone and hook into the main web server via a reverse proxy configuration (step 6).<br />
<br />
=== Step 5: .rvmrc files and ownerships ===<br />
<br />
This step is crucial for the correct behaviour of the setup. RVM seeks for .rvmrc files when changing folders; if it finds one, it reads it. In these files normally one stores a line like<br />
rvm <ruby_version>@<gemset_name><br />
so the specified environment is set at the entrance of applications' root folder.<br />
<br />
Create /srv/http/refineria/.rvmrc doing<br />
# echo "rvm ree@refinery" > /srv/http/refineria/.rvmrc<br />
, and /srv/http/navegador/.rvmrc with<br />
# echo "rvm 2.0.0@browser" > /srv/http/navegador/.rvmrc<br />
You have to enter to both application root folders now, because every first time that RVM finds a .rvmrc it asks you if you trust the given file, consequently you must validate the two files you have just created.<br />
<br />
These files aid the programs involved to find the correct gems.<br />
<br />
Apart, if applications' files and folders are not owned by the right user you will face database write-access problems. The use of rvmsudo produces ''root''-owned archives when generated by Rails; in the other hand, ''nobody'' is the user for Passenger —if you have not changed it—: who will use and should posses them. Fix this doing<br />
# chown -R nobody.nobody /srv/http/refineria /srv/http/navegador<br />
<br />
=== Step 6: Reverse proxies ===<br />
<br />
You have to start the Passenger Standalone web servers for your applications. So, do<br />
$ cd /srv/http/refineria<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
and<br />
$ cd /srv/http/navegador<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
. The first time that you run a Passenger Standalone it will perform a minor installation.<br />
<br />
Note that you are using ''unix domain'' sockets instead of the commonly-used ''TCP'' sockets; it turns out that unix domain are significantly faster than TCP sockets.<br />
<br />
{{note|If you are experimenting trouble with unix sockets, changing to TCP should work:<br />
rvmsudo passenger start -a 127.0.0.1 -p 3000 -d<br />
}}<br />
<br />
==== Launch Passenger Standalone daemons at system start-up ====<br />
<br />
''Do you have a script? Please post it here.''<br />
<br />
The systemd script below was made for a Typo blog I host at /srv/http/typo. It is located at /etc/systemd/system/passenger_typo.service. I set the Environment= tags (see "man systemd.exec") from the output of "rvm env". The only exception was PATH=, which I had to combine from my regular PATH and the output of rvm env.<br />
<br />
Note: If you do not set the "WorkingDirectory=" variable to your application folder, passenger will fail to find your app and will subsequently shut itself down.<br />
<br />
<pre><br />
[Unit]<br />
Description=Passenger Standalone Script for Typo<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
WorkingDirectory=/srv/http/typo<br />
PIDFile=/srv/http/typo/tmp/pids/passenger.pid<br />
<br />
Environment=PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo/bin:/usr/local/rvm/gems/ruby-2.0.0-p0@global/bin:/usr/local/rvm/rubies/ruby-2.0.0-p0/bin:/usr/local/rvm/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/bin/core_perl<br />
Environment=rvm_env_string=ruby-2.0.0-p0@typo<br />
Environment=rvm_path=/usr/local/rvm<br />
Environment=rvm_ruby_string=ruby-2.0.0-p0<br />
Environment=rvm_gemset_name=typo<br />
Environment=RUBY_VERSION=ruby-2.0.0-p0<br />
Environment=GEM_HOME=/usr/local/rvm/gems/ruby-2.0.0-p0@typo<br />
Environment=GEM_PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo:/usr/local/rvm/gems/ruby-2.0.0-p0@global<br />
Environment=MY_RUBY_HOME=/usr/local/rvm/rubies/ruby-2.0.0-p0<br />
Environment=IRBRC=/usr/local/rvm/rubies/ruby-2.0.0-p0/.irbrc<br />
<br />
ExecStart=/bin/bash -c "rvmsudo passenger start --socket /srv/http/typo/tmp/sockets/passenger.socket -d"<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
</pre><br />
<br />
=== Step 7: Deployment ===<br />
<br />
==== With subdomains ====<br />
<br />
Once again edit /opt/nginx/conf/nginx.conf to include some vital instructions:<br />
<br />
<pre><br />
## RefineryCMS ##<br />
<br />
server {<br />
server_name refinery.domain.com;<br />
root /srv/http/refineria/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/refineria/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
<br />
## BrowserCMS ##<br />
<br />
server {<br />
server_name browser.domain.com;<br />
root /srv/http/navegador/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/navegador/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
{{note|Or if using TCP sockets, configure the ''proxy_pass'' directive like<br />
<pre>proxy_pass http://127.0.0.1:3000;</pre><br />
}}<br />
<br />
==== Without subdomains ====<br />
<br />
If you for some reason do not want to host each application on its own subdomain but rather in a url like: {{ic|site.com/railsapp}} then you could do something like this in your config:<br />
<br />
<pre><br />
server {<br />
server_name site.com;<br />
#Base for the html files etc<br />
root /srv/http/;<br />
<br />
#First application you want hosted under domain site.com/railsapp<br />
location /railsapp {<br />
root /srv/http/railsapp/public;<br />
#you may need to change passenger_base_uri to be the uri you want to point at, ie:<br />
#passenger_base_uri /railsapp;<br />
#but probably only if you are using the other solution with passenger phusion<br />
proxy_pass http://unix:/srv/http/railsapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
<br />
#Second applicatino you want hosted under domain site.com/anotherapp<br />
location /anotherapp {<br />
root /srv/http/anotherapp/public;<br />
#same thing about the passenger_base_uri here, but with value /anotherapp instead<br />
proxy_pass http://unix:/srv/http/anotherapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
At this point you are in conditions to run Nginx with:<br />
<br />
# systemctl start nginx<br />
<br />
and to access both CMSs through ''refinery.domain.com'' and ''browser.domain.com''.<br />
<br />
=== References ===<br />
<br />
* http://beginrescueend.com/integration/passenger<br />
* http://blog.phusion.nl/2010/09/21/phusion-passenger-running-multiple-ruby-versions<br />
* http://www.ruby-journal.com/how-to-setup-rails-app-with-puma-and-nginx/<br />
* https://www.digitalocean.com/community/tutorials/how-to-deploy-a-rails-app-with-puma-and-nginx-on-ubuntu-14-04<br />
<br />
== See also ==<br />
<br />
* [[Ruby]]<br />
* [[Nginx]]<br />
* [[LAMP]]<br />
* [[MySQL]]<br />
<br />
== References ==<br />
<br />
* Ruby on Rails http://rubyonrails.org/download.<br />
* Mongrel http://mongrel.rubyforge.org.</div>Stbinanhttps://wiki.archlinux.org/index.php?title=Ruby_on_Rails&diff=396469Ruby on Rails2015-08-29T17:39:17Z<p>Stbinan: /* Puma (with Nginx as reverse proxy server) */</p>
<hr />
<div>[[Category:Web server]]<br />
[[ja:Ruby on Rails]]<br />
[[zh-CN:Ruby on Rails]]<br />
[http://rubyonrails.org/ Ruby on Rails], often shortened to Rails or RoR, is an open source web application framework for the Ruby programming language. It is intended to be used with an Agile development methodology that is used by web developers for rapid development.<br />
<br />
This document describes how to set up the Ruby on Rails Framework on an Arch Linux system.<br />
<br />
== Installation ==<br />
<br />
Ruby on Rails requires [[Ruby]] to be installed, so read that article first for installation instructions. The {{pkg|nodejs}} package is also required.<br />
<br />
Ruby on Rails itself can be installed multiple ways:<br />
<br />
=== Option A: via RubyGems ===<br />
<br />
{{Note|You can also install Rails system-wide using Gems. To do this, run the following commands as root and append them with {{ic|--no-user-install}}. Please read [[Ruby#Installing gems per-user or system-wide]] for possible dangers of using RubyGem in this way.}}<br />
<br />
The following command will install Rails for the current user:<br />
$ gem install rails<br />
<br />
Building the documentation takes a while. If you want to skip it, append {{ic|--no-document}} to the install command.<br />
$ gem install rails --no-document<br />
<br />
gem is a package manager for Ruby modules, somewhat like pacman is to Arch Linux. To update your gems, simply run:<br />
$ gem update<br />
<br />
=== Option B: via pacgem ===<br />
<br />
You can install Rails using {{AUR|pacgem}}{{Broken package link|{{aur-mirror|pacgem}}}} from the [[AUR]]. Pacgem automatically creates PKGBUILDs and Arch packages for each of the gems. These packages will then be installed using pacman.<br />
# pacgem rails<br />
<br />
The gem packages can be updated with<br />
# pacgem -u<br />
<br />
=== Option C: from the AUR ===<br />
<br />
{{Warning|This is not recommended, as this might not include the latest Rails version, and additional dependencies may be introduced that may require you to run {{Ic|gem install}} anyway.}}<br />
<br />
There is a {{AUR|ruby-rails}} package available in the [[AUR]].<br />
<br />
=== Option D: from Quarry binary repository ===<br />
<br />
[[pacman|Install]] ''ruby-rails'' from the unofficial [[Unofficial user repositories#quarry|quarry]] repository.<br />
<br />
== Configuration ==<br />
<br />
Rails is bundled with a basic HTTP server called WeBrick. You can create a test application to test it. First, create an application with the rails command:<br />
<br />
$ rails new testapp_name<br />
<br />
{{Note|If you get an error like {{ic|Errno::ENOENT: No such file or directory (...) An error occurred while installing x, and Bundler cannot continue.}}, you might have to configure [[Ruby#Bundler|Bundler]] so that it installs gems per-user and not system-wide. Alternatively, run {{ic|# rails new testapp_name}} once as root. If it has completed successfully, delete {{ic|testapp_name/}} and run {{ic|$ rails new testapp_name}} again as a regular user.}}<br />
{{Note|If you get an error message like this:<br />
{{ic|... FetchError: SSL_connect returned&#61;1 errno&#61; 0 state&#61;SSLv2/v3 read server hello A: sslv3 alert handshake<br />
failure <nowiki>(https://s3.amazonaws.com/ production.s3.rubygems.org/gems/rake-10.0.3.gem)</nowiki> }}<br />
install {{Pkg|nodejs}} and try again.}}<br />
<br />
This creates a new folder inside your current working directory. <br />
<br />
$ cd testapp_name<br />
<br />
Next start the web server. It listens on port 3000 by default:<br />
<br />
$ rails server<br />
<br />
Now visit the testapp_name website on your local machine by opening <nowiki>http://localhost:3000</nowiki> in your browser<br />
{{Note|If Ruby complains about not being able to find a JavaScript runtime, install {{Pkg|nodejs}}.}}<br />
<br />
A test-page should shown greeting you "Welcome aboard".<br />
<br />
== Application servers ==<br />
<br />
The built-in Ruby On Rails HTTP server (WeBrick) is convenient for basic development, but it is not recommended for production use. Instead, you should use an application server such as [[#Thin]], [[#Unicorn]] or [[#Apache/Nginx (using Phusion Passenger)|Phusion Passenger]].<br />
<br />
=== Thin ===<br />
<br />
[http://code.macournoyer.com/thin/ Thin] is a fast and very simple Ruby web server.<br />
<br />
First install thin gem:<br />
$ gem install thin<br />
<br />
Then start it using:<br />
$ thin start<br />
<br />
=== Unicorn ===<br />
<br />
Unicorn is an application server that cannot talk directly to clients. Instead, a web server must sit between clients and Unicorn, proxying requests as needed. [http://unicorn.bogomips.org/ Unicorn] is loosely based on Mongrel. It is used by Github, and it uses an architecture that tries hard to find the best child for handling a request. [https://github.com/blog/517-unicorn Explanation of differences between Unicorn and Mongrel].<br />
<br />
Install the Unicorn gem:<br />
# gem install unicorn<br />
<br />
Then create a configuration file for your application in {{ic|/etc/unicorn/}}. For example; here is a configuration example (Based on [http://www.warden.pl/2011/01/07/running-redmine-under-unicorn-in-debian/]) for Redmine:<br />
<br />
{{hc|/etc/unicorn/redmine.ru|<nowiki><br />
working_directory "/srv/http/redmine"<br />
pid "/tmp/redmine.pid"<br />
<br />
preload_app true<br />
timeout 60<br />
worker_processes 4<br />
listen 4000<br />
stderr_path('/var/log/unicorn.log')<br />
<br />
GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true<br />
<br />
after_fork do |server, worker|<br />
#start the worker on port 4000, 4001, 4002 etc...<br />
addr = "0.0.0.0:#{4000 + worker.nr}"<br />
# infinite tries to start the worker<br />
server.listen(addr, :tries => -1, :delay => -1, :backlog => 128)<br />
<br />
#Drop privileges if running as root<br />
worker.user('nobody', 'nobody') if Process.euid == 0<br />
end<br />
</nowiki>}}<br />
<br />
Start it using:<br />
# /usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
==== Systemd service ====<br />
<br />
Put the following contents in {{ic|/etc/systemd/system/unicorn.service}}:<br />
{{hc|/etc/systemd/system/unicorn.service|2=<br />
[Unit]<br />
Description=Unicorn application server<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
User=redmine<br />
ExecStart=/usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
}}<br />
<br />
You can now easily start and stop unicorn using systemctl<br />
<br />
==== Nginx Configuration ====<br />
<br />
After setting up [[Nginx]], configure unicorn as an upstream server using something like this (Warning: this is a stripped example. It probably does not work without additional configuration):<br />
{{bc|1=<br />
http {<br />
upstream unicorn {<br />
server 127.0.0.1:4000 fail_timeout=0;<br />
server 127.0.0.1:4001 fail_timeout=0;<br />
server 127.0.0.1:4002 fail_timeout=0;<br />
server 127.0.0.1:4003 fail_timeout=0;<br />
}<br />
<br />
server {<br />
listen 80 default;<br />
server_name YOURHOSTNAMEHERE;<br />
<br />
location / {<br />
root /srv/http/redmine/public;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
proxy_pass http://unicorn;<br />
}<br />
}<br />
}<br />
}}<br />
<br />
=== Apache/Nginx (using Phusion Passenger) ===<br />
<br />
[http://www.modrails.com/ Passenger] also known as {{ic|mod_rails}} is a module available for [[Nginx]] and [[Apache]], that greatly simplifies setting up a Rails server environment. Nginx does not support modules as Apache and has to be compiled with {{ic|mod_rails}} in order to support Passenger; let Passenger compile it for you. As for Apache, let Passenger set up the module for you.<br />
<br />
Start by installing the 'passenger' gem:<br />
# gem install passenger<br />
<br />
If you are aiming to use [[Apache]], run:<br />
# passenger-install-apache2-module<br />
<br />
In case a rails application is deployed with a sub-URI, like http://example.com/yourapplication, some additional configuration is required, see [http://www.modrails.com/documentation/Users%20guide%20Apache.html#deploying_rails_to_sub_uri the modrails documentation]<br />
<br />
For [[Nginx]]:<br />
# passenger-install-nginx-module<br />
<br />
The installer will provide you with any additional information regarding the installation (such as installing additional libraries).<br />
<br />
To serve an application with Nginx, configure it as follows:<br />
<pre><br />
server {<br />
server_name app.example.org;<br />
root path_to_app/public; # Be sure to point to 'public' folder!<br />
passenger_enabled on;<br />
rails_env development; # Rails environment.<br />
}<br />
</pre><br />
<br />
=== Puma (with Nginx as reverse proxy server) ===<br />
<br />
[http://puma.io/ Puma] ([https://github.com/puma/puma Github Page]) is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications, and is considered the replacement for Webrick and Mongrel. It was designed to be the go-to server for Rubinius, but also works well with JRuby and MRI. While reverse proxy server would acts as a load balancer that routes all external requests to a pool of web apps.<br />
<br />
For a webserver it is better to use a server user and group, check [[Users and groups#Example adding a user]], below use {{ic|rails}} as user name and {{ic|server}} as group name, also {{ic|my_app}} as rails app name.<br />
<br />
Start by copying your app to /var/www/my_app. And set new ownership with<br />
# cd /var/www/<br />
# chown -R rails:server my_app<br />
<br />
and permission for user with<br />
# chmod -R 775 my_app<br />
<br />
Then add {{ic|puma gem}} in the Gemfile and install with<br />
$ cd my_app <br />
$ bundle install<br />
<br />
Also install {{ic|nginx}} by pacman.<br />
<br />
Under your app folder, create sockets, pid and log folder with<br />
$ mkdir -p shared/pids shared/sockets shared/log<br />
<br />
Backup nginx.conf with<br />
# cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup<br />
<br />
Then create a new nginx.conf file with your favorite editor, copy codes below and modify as you like:<br />
<pre><br />
#user html;<br />
worker_processes 1; # this may connect with the worker numbers puma can use.<br />
<br />
#error_log logs/error.log;<br />
#error_log logs/error.log notice;<br />
#error_log logs/error.log info;<br />
<br />
#pid logs/nginx.pid;<br />
<br />
<br />
events {<br />
worker_connections 1024;<br />
}<br />
<br />
http {<br />
upstream app {<br />
# Path to Puma SOCK file, as defined previously<br />
server unix:/var/www/my_app/shared/sockets/puma.sock;<br />
}<br />
<br />
server {<br />
listen 80;<br />
server_name localhost; # or your server name<br />
<br />
root /var/www/my_app/public;<br />
<br />
try_files $uri/index.html $uri @app;<br />
<br />
location @app {<br />
proxy_pass http://app;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
}<br />
<br />
error_page 500 502 503 504 /500.html;<br />
client_max_body_size 4G;<br />
keepalive_timeout 10;<br />
}<br />
}</pre><br />
<br />
Start nginx service with<br />
# systemctl start nginx<br />
<br />
<br />
There are several ways to start puma server, two ways are recommended below:<br />
<br />
In common create file {{ic|config/puma.rb}}, copy codes below and modify as you like:<br />
<pre><br />
# Change to match your CPU core count<br />
# You can check available worker numbers with $ grep -c processor /proc/cpuinfo<br />
# also see the comment in the nginx.conf<br />
workers 2<br />
<br />
# Min and Max threads per worker<br />
#threads 1, 6<br />
<br />
app_dir = File.expand_path("../..", __FILE__)<br />
shared_dir = "#{app_dir}/shared"<br />
<br />
# Default to production<br />
#rails_env = ENV['RAILS_ENV'] || "production"<br />
#environment rails_env<br />
<br />
# Set up socket location<br />
bind "unix://#{shared_dir}/sockets/puma.sock"<br />
<br />
# Logging<br />
#stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true<br />
<br />
# Set master PID and state locations<br />
pidfile "#{shared_dir}/pids/puma.pid"<br />
#state_path "#{shared_dir}/pids/puma.state"<br />
#activate_control_app<br />
<br />
#on_worker_boot do<br />
# require "active_record"<br />
# ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished<br />
# ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])<br />
#end</pre><br />
<br />
==== Option A: With config file ====<br />
<br />
Start server with<br />
$ bundle exec puma -C config/puma.rb<br />
<br />
You can also run it in background with parameter {{ic|-d}} and check with<br />
$ ps aux| grep puma<br />
when you want to {{ic|kill}} it.<br />
<br />
==== Option 2: by systemd ====<br />
<br />
Create a new systemd unit {{ic|puma.service}} under ~/.config/systemd/user/ and copy codes below<br />
<pre><br />
[Unit]<br />
Description=Puma application server<br />
After=network.target<br />
<br />
[Service]<br />
WorkingDirectory=/var/www/my_app<br />
#Environment=RAILS_ENV=production<br />
#User=rails<br />
PIDFile=/var/www/my_app/shared/pids/puma.pid<br />
ExecStart=/home/rails/.gem/ruby/2.2.0/bin/bundle exec \<br />
/home/rails/.gem/ruby/2.2.0/bin/puma \<br />
-C /var/www/my_app/config/puma.rb<br />
<br />
[Install]<br />
WantedBy=multi-user.target</pre><br />
<br />
Hint: For ExecStart, if you've installed gem globally, you can change routes to /usr/local/bin/ in ExecStart.<br />
<br />
Then start puma with<br />
$ systemctl --user start puma<br />
<br />
For further reading take a look at [[#References]]. Also, for easily deploying app in production mode, you can try [https://github.com/capistrano/capistrano capistrano]<br />
<br />
== Databases ==<br />
<br />
Most web applications will need to interact with some sort of database. ActiveRecord (the ORM used by Rails to provide database abstraction) supports several database vendors, the most popular of which are MySQL, SQLite, and PostgreSQL.<br />
<br />
=== SQLite ===<br />
<br />
SQLite is the default lightweight database for Ruby on Rails. To enable SQLite, simply install {{Pkg|sqlite}}.<br />
<br />
=== PostgreSQL ===<br />
<br />
Install {{Pkg|postgresql}}.<br />
<br />
=== MySQL ===<br />
<br />
First, install and configure a MySQL server. Please refer to [[MySQL]] on how to do this.<br />
<br />
A gem with some native extensions is required, probably best installed as root:<br />
# gem install mysql<br />
<br />
You can generate a rails application configured for MySQL by using the {{ic|-d}} parameter:<br />
$ rails new testapp_name -d mysql<br />
<br />
You then need to edit {{ic|config/database.yml}}. Rails uses different databases for development, testing, production and other environments. Here is an example development configuration for MySQL running on localhost:<br />
<br />
development:<br />
adapter: mysql<br />
database: my_application_database<br />
username: development<br />
password: my_secret_password<br />
<br />
Note that you do not have to actually create the database using MySQL, as this can be done via Rails with:<br />
# rake db:create<br />
<br />
If no errors are shown, then your database has been created and Rails can talk to your MySQL database.<br />
<br />
== The Perfect Rails Setup ==<br />
<br />
''Phusion Passenger running multiple Ruby versions.''<br />
<br />
* [https://www.archlinux.org/ Arch Linux]: A simple, lightweight distribution. ;)<br />
* [http://www.nginx.org/ Nginx]: A fast and lightweight '''web server''' with a strong focus on high concurrency, performance and low memory usage.<br />
* [http://www.modrails.com/ Passenger] (a.k.a. mod_rails or mod_rack): Supports both Apache and Nginx web servers. It makes deployment of Ruby web applications, such as those built on Ruby on Rails web framework, a breeze.<br />
* [https://rvm.io/ Ruby Version Manager] (RVM): A command-line tool which allows you to easily install, manage, and work with multiple Ruby environments from interpreters to sets of gems. RVM lets you deploy each project with its own completely self-contained and dedicated environment —from the specific version of ruby, all the way down to the precise set of required gems to run your application—.<br />
* [http://sqlite.org/ SQLite]: The default lightweight '''database''' for Ruby on Rails.<br />
<br />
=== Step 0: SQLite ===<br />
<br />
Install {{Pkg|sqlite}}.<br />
<br />
{{note|Of course SQLite is not critical in this setup, you can use MySQL and PostgreSQL as well.}}<br />
<br />
=== Step 1: RVM ===<br />
<br />
Make a multi-user [[RVM]] installation as specified [[RVM#Multi-user_installation|here]].<br />
<br />
In the 'adding users to the rvm group' step, do<br />
# usermod -a -G rvm http<br />
# usermod -a -G rvm nobody<br />
<br />
{{ic|http}} and {{ic|nobody}} are the users related to Nginx and Passenger, respectively.<br />
<br />
{{note|Maybe adding the 'nobody' user to the 'rvm' group is not necessary.}}<br />
<br />
=== Step 2: Rubies ===<br />
<br />
Once you have a working RVM installation in your hands, it is time to install the latest Ruby interpreter<br />
{{Note|During the installation of Ruby patches will be applied. Consider installing the {{ic|base-devel}} group beforehand.}}<br />
<br />
$ rvm install 2.0.0<br />
<br />
{{Note| It may be useful to delete the 'global' gemsets of the environments that have web applications. Their gems might somehow interfere with Passenger. In that case, a {{ic|rvm 2.0.0 do gemset delete global}} is sufficient.}}<br />
<br />
=== Step 3: Nginx with Passenger support ===<br />
<br />
Run the following to allow passenger install nginx:<br />
$ rvm use 2.0.0 <br />
$ gem install passenger<br />
$ rvmsudo passenger-install-nginx-module<br />
<br />
The passenger gem will be put into the ''default'' gemset.<br />
<br />
This will download the sources of Nginx, compile and install it for you. It will guide you through all the process. Note that the default location for Nginx will be {{ic|/opt/nginx}}.<br />
<br />
{{Note|If you encounter a compilation error regarding Boost threads, see [https://bbs.archlinux.org/viewtopic.php?id&#61;139164 this] article.}}<br />
<br />
After completion, add the following two lines into the 'http block' at {{ic|/opt/nginx/conf/nginx.conf}} that look like:<br />
<br />
http { <br />
...<br />
passenger_root /usr/local/rvm/gems/ruby-2.0.0-p353/gems/passenger-3.0.9;<br />
passenger_ruby /usr/local/rvm/wrappers/ruby-2.0.0-p353/ruby;<br />
...<br />
}<br />
<br />
{{Note|This step is currently being done automatically by the installer script.}}<br />
<br />
=== Step 4: Gemsets and Apps ===<br />
<br />
For each Rails application you should have a gemset. Suppose that you want to try [http://refinerycms.com RefineryCMS] against [http://www.browsercms.org BrowserCMS], two open-source Content Management Systems based on Rails.<br />
<br />
Install RefineryCMS first:<br />
<br />
$ rvm use 2.0.0@refinery --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install refinerycms refinerycms-i18n sqlite3<br />
<br />
Deploy a RefineryCMS instance called ''refineria'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo refinerycms refineria<br />
<br />
Install BrowserCMS in a different gemset:<br />
<br />
$ rvm use 2.0.0@browser --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install browsercms sqlite3<br />
<br />
Deploy a BrowserCMS instance called ''navegador'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo browsercms demo navegador<br />
$ cd /srv/http/navegador<br />
$ rvmsudo rake db:install<br />
<br />
=== Passenger for Nginx and Passenger Standalone ===<br />
<br />
Observe that the passenger gem was installed three times and with different intentions; in the environments<br />
* ''2.0.0'' => for Nginx,<br />
* ''2.0.0@refinery'' => Standalone<br />
* ''2.0.0@browser'' => Standalone<br />
<br />
The strategy is to combine Passenger for Nginx with Passenger Standalone. One must first identify the Ruby environment (interpreter plus gemset) that one uses the most; in this setup the Ruby interpreter and the default gemset were selected. One then proceeds with setting up Passenger for Nginx to use that environment (step 3).<br />
* Applications within the chosen environment can be served as in [[#Apache.2FNginx .28using Phusion Passenger.29|Apache/Nginx (using Phusion Passenger)]], page up in this article.<br />
* All applications that are to use a different Ruby version and/or gemset can be served separately through Passenger Standalone and hook into the main web server via a reverse proxy configuration (step 6).<br />
<br />
=== Step 5: .rvmrc files and ownerships ===<br />
<br />
This step is crucial for the correct behaviour of the setup. RVM seeks for .rvmrc files when changing folders; if it finds one, it reads it. In these files normally one stores a line like<br />
rvm <ruby_version>@<gemset_name><br />
so the specified environment is set at the entrance of applications' root folder.<br />
<br />
Create /srv/http/refineria/.rvmrc doing<br />
# echo "rvm ree@refinery" > /srv/http/refineria/.rvmrc<br />
, and /srv/http/navegador/.rvmrc with<br />
# echo "rvm 2.0.0@browser" > /srv/http/navegador/.rvmrc<br />
You have to enter to both application root folders now, because every first time that RVM finds a .rvmrc it asks you if you trust the given file, consequently you must validate the two files you have just created.<br />
<br />
These files aid the programs involved to find the correct gems.<br />
<br />
Apart, if applications' files and folders are not owned by the right user you will face database write-access problems. The use of rvmsudo produces ''root''-owned archives when generated by Rails; in the other hand, ''nobody'' is the user for Passenger —if you have not changed it—: who will use and should posses them. Fix this doing<br />
# chown -R nobody.nobody /srv/http/refineria /srv/http/navegador<br />
<br />
=== Step 6: Reverse proxies ===<br />
<br />
You have to start the Passenger Standalone web servers for your applications. So, do<br />
$ cd /srv/http/refineria<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
and<br />
$ cd /srv/http/navegador<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
. The first time that you run a Passenger Standalone it will perform a minor installation.<br />
<br />
Note that you are using ''unix domain'' sockets instead of the commonly-used ''TCP'' sockets; it turns out that unix domain are significantly faster than TCP sockets.<br />
<br />
{{note|If you are experimenting trouble with unix sockets, changing to TCP should work:<br />
rvmsudo passenger start -a 127.0.0.1 -p 3000 -d<br />
}}<br />
<br />
==== Launch Passenger Standalone daemons at system start-up ====<br />
<br />
''Do you have a script? Please post it here.''<br />
<br />
The systemd script below was made for a Typo blog I host at /srv/http/typo. It is located at /etc/systemd/system/passenger_typo.service. I set the Environment= tags (see "man systemd.exec") from the output of "rvm env". The only exception was PATH=, which I had to combine from my regular PATH and the output of rvm env.<br />
<br />
Note: If you do not set the "WorkingDirectory=" variable to your application folder, passenger will fail to find your app and will subsequently shut itself down.<br />
<br />
<pre><br />
[Unit]<br />
Description=Passenger Standalone Script for Typo<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
WorkingDirectory=/srv/http/typo<br />
PIDFile=/srv/http/typo/tmp/pids/passenger.pid<br />
<br />
Environment=PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo/bin:/usr/local/rvm/gems/ruby-2.0.0-p0@global/bin:/usr/local/rvm/rubies/ruby-2.0.0-p0/bin:/usr/local/rvm/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/bin/core_perl<br />
Environment=rvm_env_string=ruby-2.0.0-p0@typo<br />
Environment=rvm_path=/usr/local/rvm<br />
Environment=rvm_ruby_string=ruby-2.0.0-p0<br />
Environment=rvm_gemset_name=typo<br />
Environment=RUBY_VERSION=ruby-2.0.0-p0<br />
Environment=GEM_HOME=/usr/local/rvm/gems/ruby-2.0.0-p0@typo<br />
Environment=GEM_PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo:/usr/local/rvm/gems/ruby-2.0.0-p0@global<br />
Environment=MY_RUBY_HOME=/usr/local/rvm/rubies/ruby-2.0.0-p0<br />
Environment=IRBRC=/usr/local/rvm/rubies/ruby-2.0.0-p0/.irbrc<br />
<br />
ExecStart=/bin/bash -c "rvmsudo passenger start --socket /srv/http/typo/tmp/sockets/passenger.socket -d"<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
</pre><br />
<br />
=== Step 7: Deployment ===<br />
<br />
==== With subdomains ====<br />
<br />
Once again edit /opt/nginx/conf/nginx.conf to include some vital instructions:<br />
<br />
<pre><br />
## RefineryCMS ##<br />
<br />
server {<br />
server_name refinery.domain.com;<br />
root /srv/http/refineria/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/refineria/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
<br />
## BrowserCMS ##<br />
<br />
server {<br />
server_name browser.domain.com;<br />
root /srv/http/navegador/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/navegador/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
{{note|Or if using TCP sockets, configure the ''proxy_pass'' directive like<br />
<pre>proxy_pass http://127.0.0.1:3000;</pre><br />
}}<br />
<br />
==== Without subdomains ====<br />
<br />
If you for some reason do not want to host each application on its own subdomain but rather in a url like: {{ic|site.com/railsapp}} then you could do something like this in your config:<br />
<br />
<pre><br />
server {<br />
server_name site.com;<br />
#Base for the html files etc<br />
root /srv/http/;<br />
<br />
#First application you want hosted under domain site.com/railsapp<br />
location /railsapp {<br />
root /srv/http/railsapp/public;<br />
#you may need to change passenger_base_uri to be the uri you want to point at, ie:<br />
#passenger_base_uri /railsapp;<br />
#but probably only if you are using the other solution with passenger phusion<br />
proxy_pass http://unix:/srv/http/railsapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
<br />
#Second applicatino you want hosted under domain site.com/anotherapp<br />
location /anotherapp {<br />
root /srv/http/anotherapp/public;<br />
#same thing about the passenger_base_uri here, but with value /anotherapp instead<br />
proxy_pass http://unix:/srv/http/anotherapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
At this point you are in conditions to run Nginx with:<br />
<br />
# systemctl start nginx<br />
<br />
and to access both CMSs through ''refinery.domain.com'' and ''browser.domain.com''.<br />
<br />
=== References ===<br />
<br />
* http://beginrescueend.com/integration/passenger<br />
* http://blog.phusion.nl/2010/09/21/phusion-passenger-running-multiple-ruby-versions<br />
* http://www.ruby-journal.com/how-to-setup-rails-app-with-puma-and-nginx/<br />
* https://www.digitalocean.com/community/tutorials/how-to-deploy-a-rails-app-with-puma-and-nginx-on-ubuntu-14-04<br />
<br />
== See also ==<br />
<br />
* [[Ruby]]<br />
* [[Nginx]]<br />
* [[LAMP]]<br />
* [[MySQL]]<br />
<br />
== References ==<br />
<br />
* Ruby on Rails http://rubyonrails.org/download.<br />
* Mongrel http://mongrel.rubyforge.org.</div>Stbinanhttps://wiki.archlinux.org/index.php?title=Ruby_on_Rails&diff=396461Ruby on Rails2015-08-29T16:23:38Z<p>Stbinan: /* Puma (with Nginx as reverse proxy server) */</p>
<hr />
<div>[[Category:Web server]]<br />
[[ja:Ruby on Rails]]<br />
[[zh-CN:Ruby on Rails]]<br />
[http://rubyonrails.org/ Ruby on Rails], often shortened to Rails or RoR, is an open source web application framework for the Ruby programming language. It is intended to be used with an Agile development methodology that is used by web developers for rapid development.<br />
<br />
This document describes how to set up the Ruby on Rails Framework on an Arch Linux system.<br />
<br />
== Installation ==<br />
<br />
Ruby on Rails requires [[Ruby]] to be installed, so read that article first for installation instructions. The {{pkg|nodejs}} package is also required.<br />
<br />
Ruby on Rails itself can be installed multiple ways:<br />
<br />
=== Option A: via RubyGems ===<br />
<br />
{{Note|You can also install Rails system-wide using Gems. To do this, run the following commands as root and append them with {{ic|--no-user-install}}. Please read [[Ruby#Installing gems per-user or system-wide]] for possible dangers of using RubyGem in this way.}}<br />
<br />
The following command will install Rails for the current user:<br />
$ gem install rails<br />
<br />
Building the documentation takes a while. If you want to skip it, append {{ic|--no-document}} to the install command.<br />
$ gem install rails --no-document<br />
<br />
gem is a package manager for Ruby modules, somewhat like pacman is to Arch Linux. To update your gems, simply run:<br />
$ gem update<br />
<br />
=== Option B: via pacgem ===<br />
<br />
You can install Rails using {{AUR|pacgem}}{{Broken package link|{{aur-mirror|pacgem}}}} from the [[AUR]]. Pacgem automatically creates PKGBUILDs and Arch packages for each of the gems. These packages will then be installed using pacman.<br />
# pacgem rails<br />
<br />
The gem packages can be updated with<br />
# pacgem -u<br />
<br />
=== Option C: from the AUR ===<br />
<br />
{{Warning|This is not recommended, as this might not include the latest Rails version, and additional dependencies may be introduced that may require you to run {{Ic|gem install}} anyway.}}<br />
<br />
There is a {{AUR|ruby-rails}} package available in the [[AUR]].<br />
<br />
=== Option D: from Quarry binary repository ===<br />
<br />
[[pacman|Install]] ''ruby-rails'' from the unofficial [[Unofficial user repositories#quarry|quarry]] repository.<br />
<br />
== Configuration ==<br />
<br />
Rails is bundled with a basic HTTP server called WeBrick. You can create a test application to test it. First, create an application with the rails command:<br />
<br />
$ rails new testapp_name<br />
<br />
{{Note|If you get an error like {{ic|Errno::ENOENT: No such file or directory (...) An error occurred while installing x, and Bundler cannot continue.}}, you might have to configure [[Ruby#Bundler|Bundler]] so that it installs gems per-user and not system-wide. Alternatively, run {{ic|# rails new testapp_name}} once as root. If it has completed successfully, delete {{ic|testapp_name/}} and run {{ic|$ rails new testapp_name}} again as a regular user.}}<br />
{{Note|If you get an error message like this:<br />
{{ic|... FetchError: SSL_connect returned&#61;1 errno&#61; 0 state&#61;SSLv2/v3 read server hello A: sslv3 alert handshake<br />
failure <nowiki>(https://s3.amazonaws.com/ production.s3.rubygems.org/gems/rake-10.0.3.gem)</nowiki> }}<br />
install {{Pkg|nodejs}} and try again.}}<br />
<br />
This creates a new folder inside your current working directory. <br />
<br />
$ cd testapp_name<br />
<br />
Next start the web server. It listens on port 3000 by default:<br />
<br />
$ rails server<br />
<br />
Now visit the testapp_name website on your local machine by opening <nowiki>http://localhost:3000</nowiki> in your browser<br />
{{Note|If Ruby complains about not being able to find a JavaScript runtime, install {{Pkg|nodejs}}.}}<br />
<br />
A test-page should shown greeting you "Welcome aboard".<br />
<br />
== Application servers ==<br />
<br />
The built-in Ruby On Rails HTTP server (WeBrick) is convenient for basic development, but it is not recommended for production use. Instead, you should use an application server such as [[#Thin]], [[#Unicorn]] or [[#Apache/Nginx (using Phusion Passenger)|Phusion Passenger]].<br />
<br />
=== Thin ===<br />
<br />
[http://code.macournoyer.com/thin/ Thin] is a fast and very simple Ruby web server.<br />
<br />
First install thin gem:<br />
$ gem install thin<br />
<br />
Then start it using:<br />
$ thin start<br />
<br />
=== Unicorn ===<br />
<br />
Unicorn is an application server that cannot talk directly to clients. Instead, a web server must sit between clients and Unicorn, proxying requests as needed. [http://unicorn.bogomips.org/ Unicorn] is loosely based on Mongrel. It is used by Github, and it uses an architecture that tries hard to find the best child for handling a request. [https://github.com/blog/517-unicorn Explanation of differences between Unicorn and Mongrel].<br />
<br />
Install the Unicorn gem:<br />
# gem install unicorn<br />
<br />
Then create a configuration file for your application in {{ic|/etc/unicorn/}}. For example; here is a configuration example (Based on [http://www.warden.pl/2011/01/07/running-redmine-under-unicorn-in-debian/]) for Redmine:<br />
<br />
{{hc|/etc/unicorn/redmine.ru|<nowiki><br />
working_directory "/srv/http/redmine"<br />
pid "/tmp/redmine.pid"<br />
<br />
preload_app true<br />
timeout 60<br />
worker_processes 4<br />
listen 4000<br />
stderr_path('/var/log/unicorn.log')<br />
<br />
GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true<br />
<br />
after_fork do |server, worker|<br />
#start the worker on port 4000, 4001, 4002 etc...<br />
addr = "0.0.0.0:#{4000 + worker.nr}"<br />
# infinite tries to start the worker<br />
server.listen(addr, :tries => -1, :delay => -1, :backlog => 128)<br />
<br />
#Drop privileges if running as root<br />
worker.user('nobody', 'nobody') if Process.euid == 0<br />
end<br />
</nowiki>}}<br />
<br />
Start it using:<br />
# /usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
==== Systemd service ====<br />
<br />
Put the following contents in {{ic|/etc/systemd/system/unicorn.service}}:<br />
{{hc|/etc/systemd/system/unicorn.service|2=<br />
[Unit]<br />
Description=Unicorn application server<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
User=redmine<br />
ExecStart=/usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
}}<br />
<br />
You can now easily start and stop unicorn using systemctl<br />
<br />
==== Nginx Configuration ====<br />
<br />
After setting up [[Nginx]], configure unicorn as an upstream server using something like this (Warning: this is a stripped example. It probably does not work without additional configuration):<br />
{{bc|1=<br />
http {<br />
upstream unicorn {<br />
server 127.0.0.1:4000 fail_timeout=0;<br />
server 127.0.0.1:4001 fail_timeout=0;<br />
server 127.0.0.1:4002 fail_timeout=0;<br />
server 127.0.0.1:4003 fail_timeout=0;<br />
}<br />
<br />
server {<br />
listen 80 default;<br />
server_name YOURHOSTNAMEHERE;<br />
<br />
location / {<br />
root /srv/http/redmine/public;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
proxy_pass http://unicorn;<br />
}<br />
}<br />
}<br />
}}<br />
<br />
=== Apache/Nginx (using Phusion Passenger) ===<br />
<br />
[http://www.modrails.com/ Passenger] also known as {{ic|mod_rails}} is a module available for [[Nginx]] and [[Apache]], that greatly simplifies setting up a Rails server environment. Nginx does not support modules as Apache and has to be compiled with {{ic|mod_rails}} in order to support Passenger; let Passenger compile it for you. As for Apache, let Passenger set up the module for you.<br />
<br />
Start by installing the 'passenger' gem:<br />
# gem install passenger<br />
<br />
If you are aiming to use [[Apache]], run:<br />
# passenger-install-apache2-module<br />
<br />
In case a rails application is deployed with a sub-URI, like http://example.com/yourapplication, some additional configuration is required, see [http://www.modrails.com/documentation/Users%20guide%20Apache.html#deploying_rails_to_sub_uri the modrails documentation]<br />
<br />
For [[Nginx]]:<br />
# passenger-install-nginx-module<br />
<br />
The installer will provide you with any additional information regarding the installation (such as installing additional libraries).<br />
<br />
To serve an application with Nginx, configure it as follows:<br />
<pre><br />
server {<br />
server_name app.example.org;<br />
root path_to_app/public; # Be sure to point to 'public' folder!<br />
passenger_enabled on;<br />
rails_env development; # Rails environment.<br />
}<br />
</pre><br />
<br />
=== Puma (with Nginx as reverse proxy server) ===<br />
<br />
[http://puma.io/ Puma] ([https://github.com/puma/puma Github Page]) is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications, and is considered the replacement for Webrick and Mongrel. It was designed to be the go-to server for Rubinius, but also works well with JRuby and MRI. While reverse proxy server would acts as a load balancer that routes all external requests to a pool of web apps.<br />
<br />
For a webserver it is better to use a server user and group, check [[Users and groups#Example adding a user]], below use {{ic|rails}} as user name and {{ic|server}} as group name, also {{ic|my_app}} as rails app name.<br />
<br />
Start by copying your app to /var/www/my_app. And set new ownership with<br />
# cd /var/www/<br />
# chown -R rails:server my_app<br />
<br />
and permission for user with<br />
# chmod -R 775 my_app<br />
<br />
Then add {{ic|puma gem}} in the Gemfile and install with<br />
$ cd my_app <br />
$ bundle install<br />
<br />
Also install {{ic|nginx}} by pacman.<br />
<br />
Under your app folder, create sockets, pid and log folder with<br />
$ mkdir -p shared/pids shared/sockets shared/log<br />
<br />
Backup nginx.conf with<br />
# cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup<br />
<br />
Then create a new nginx.conf file with your favorite editor, copy codes below and modify as you like:<br />
<pre><br />
#user html;<br />
worker_processes 1; # this may connect with the worker numbers puma can use.<br />
<br />
#error_log logs/error.log;<br />
#error_log logs/error.log notice;<br />
#error_log logs/error.log info;<br />
<br />
#pid logs/nginx.pid;<br />
<br />
<br />
events {<br />
worker_connections 1024;<br />
}<br />
<br />
http {<br />
upstream app {<br />
# Path to Puma SOCK file, as defined previously<br />
server unix:/var/www/my_app/shared/sockets/puma.sock;<br />
}<br />
<br />
server {<br />
listen 80;<br />
server_name localhost; # or your server name<br />
<br />
root /var/www/my_app/public;<br />
<br />
try_files $uri/index.html $uri @app;<br />
<br />
location @app {<br />
proxy_pass http://app;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
}<br />
<br />
error_page 500 502 503 504 /500.html;<br />
client_max_body_size 4G;<br />
keepalive_timeout 10;<br />
}<br />
}</pre><br />
<br />
Start nginx service with<br />
# systemctl start nginx<br />
<br />
<br />
There are several ways to start puma server, two ways are recommended below:<br />
<br />
In common create file {{ic|config/puma.rb}}, copy codes below and modify as you like:<br />
<pre><br />
# Change to match your CPU core count<br />
# You can check available worker numbers with $ grep -c processor /proc/cpuinfo<br />
# also see the comment in the nginx.conf<br />
workers 2<br />
<br />
# Min and Max threads per worker<br />
#threads 1, 6<br />
<br />
app_dir = File.expand_path("../..", __FILE__)<br />
shared_dir = "#{app_dir}/shared"<br />
<br />
# Default to production<br />
#rails_env = ENV['RAILS_ENV'] || "production"<br />
#environment rails_env<br />
<br />
# Set up socket location<br />
bind "unix://#{shared_dir}/sockets/puma.sock"<br />
<br />
# Logging<br />
#stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true<br />
<br />
# Set master PID and state locations<br />
pidfile "#{shared_dir}/pids/puma.pid"<br />
#state_path "#{shared_dir}/pids/puma.state"<br />
#activate_control_app<br />
<br />
#on_worker_boot do<br />
# require "active_record"<br />
# ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished<br />
# ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])<br />
#end</pre><br />
<br />
==== Option A: With config file ====<br />
<br />
Start server with<br />
$ bundle exec puma -C config/puma.rb<br />
<br />
You can also run it in background with parameter {{ic|-d}} and check with<br />
$ ps aux| grep puma<br />
when you want to {{ic|kill}} it.<br />
<br />
==== Option 2: by systemd ====<br />
<br />
Create a new systemd unit {{ic|puma.service}} under ~/.config/systemd/user/ and copy codes below<br />
<pre><br />
[Unit]<br />
Description=Puma application server<br />
After=network.target<br />
<br />
[Service]<br />
WorkingDirectory=/var/www/my_app<br />
#Environment=RAILS_ENV=production<br />
#User=rails<br />
PIDFile=/var/www/my_app/shared/pids/puma.pid<br />
ExecStart=/home/rails/.gem/ruby/2.2.0/bin/bundle exec \<br />
/home/rails/.gem/ruby/2.2.0/bin/puma \<br />
-C /var/www/my_app/config/puma.rb<br />
<br />
[Install]<br />
WantedBy=multi-user.target</pre><br />
<br />
Hint: For ExecStart, if you've installed gem globally, you can change routes to /usr/local/bin/ in ExecStart.<br />
<br />
Then start puma with<br />
$ systemctl --user start puma<br />
<br />
For further reading take a look at [[#References]]<br />
<br />
== Databases ==<br />
<br />
Most web applications will need to interact with some sort of database. ActiveRecord (the ORM used by Rails to provide database abstraction) supports several database vendors, the most popular of which are MySQL, SQLite, and PostgreSQL.<br />
<br />
=== SQLite ===<br />
<br />
SQLite is the default lightweight database for Ruby on Rails. To enable SQLite, simply install {{Pkg|sqlite}}.<br />
<br />
=== PostgreSQL ===<br />
<br />
Install {{Pkg|postgresql}}.<br />
<br />
=== MySQL ===<br />
<br />
First, install and configure a MySQL server. Please refer to [[MySQL]] on how to do this.<br />
<br />
A gem with some native extensions is required, probably best installed as root:<br />
# gem install mysql<br />
<br />
You can generate a rails application configured for MySQL by using the {{ic|-d}} parameter:<br />
$ rails new testapp_name -d mysql<br />
<br />
You then need to edit {{ic|config/database.yml}}. Rails uses different databases for development, testing, production and other environments. Here is an example development configuration for MySQL running on localhost:<br />
<br />
development:<br />
adapter: mysql<br />
database: my_application_database<br />
username: development<br />
password: my_secret_password<br />
<br />
Note that you do not have to actually create the database using MySQL, as this can be done via Rails with:<br />
# rake db:create<br />
<br />
If no errors are shown, then your database has been created and Rails can talk to your MySQL database.<br />
<br />
== The Perfect Rails Setup ==<br />
<br />
''Phusion Passenger running multiple Ruby versions.''<br />
<br />
* [https://www.archlinux.org/ Arch Linux]: A simple, lightweight distribution. ;)<br />
* [http://www.nginx.org/ Nginx]: A fast and lightweight '''web server''' with a strong focus on high concurrency, performance and low memory usage.<br />
* [http://www.modrails.com/ Passenger] (a.k.a. mod_rails or mod_rack): Supports both Apache and Nginx web servers. It makes deployment of Ruby web applications, such as those built on Ruby on Rails web framework, a breeze.<br />
* [https://rvm.io/ Ruby Version Manager] (RVM): A command-line tool which allows you to easily install, manage, and work with multiple Ruby environments from interpreters to sets of gems. RVM lets you deploy each project with its own completely self-contained and dedicated environment —from the specific version of ruby, all the way down to the precise set of required gems to run your application—.<br />
* [http://sqlite.org/ SQLite]: The default lightweight '''database''' for Ruby on Rails.<br />
<br />
=== Step 0: SQLite ===<br />
<br />
Install {{Pkg|sqlite}}.<br />
<br />
{{note|Of course SQLite is not critical in this setup, you can use MySQL and PostgreSQL as well.}}<br />
<br />
=== Step 1: RVM ===<br />
<br />
Make a multi-user [[RVM]] installation as specified [[RVM#Multi-user_installation|here]].<br />
<br />
In the 'adding users to the rvm group' step, do<br />
# usermod -a -G rvm http<br />
# usermod -a -G rvm nobody<br />
<br />
{{ic|http}} and {{ic|nobody}} are the users related to Nginx and Passenger, respectively.<br />
<br />
{{note|Maybe adding the 'nobody' user to the 'rvm' group is not necessary.}}<br />
<br />
=== Step 2: Rubies ===<br />
<br />
Once you have a working RVM installation in your hands, it is time to install the latest Ruby interpreter<br />
{{Note|During the installation of Ruby patches will be applied. Consider installing the {{ic|base-devel}} group beforehand.}}<br />
<br />
$ rvm install 2.0.0<br />
<br />
{{Note| It may be useful to delete the 'global' gemsets of the environments that have web applications. Their gems might somehow interfere with Passenger. In that case, a {{ic|rvm 2.0.0 do gemset delete global}} is sufficient.}}<br />
<br />
=== Step 3: Nginx with Passenger support ===<br />
<br />
Run the following to allow passenger install nginx:<br />
$ rvm use 2.0.0 <br />
$ gem install passenger<br />
$ rvmsudo passenger-install-nginx-module<br />
<br />
The passenger gem will be put into the ''default'' gemset.<br />
<br />
This will download the sources of Nginx, compile and install it for you. It will guide you through all the process. Note that the default location for Nginx will be {{ic|/opt/nginx}}.<br />
<br />
{{Note|If you encounter a compilation error regarding Boost threads, see [https://bbs.archlinux.org/viewtopic.php?id&#61;139164 this] article.}}<br />
<br />
After completion, add the following two lines into the 'http block' at {{ic|/opt/nginx/conf/nginx.conf}} that look like:<br />
<br />
http { <br />
...<br />
passenger_root /usr/local/rvm/gems/ruby-2.0.0-p353/gems/passenger-3.0.9;<br />
passenger_ruby /usr/local/rvm/wrappers/ruby-2.0.0-p353/ruby;<br />
...<br />
}<br />
<br />
{{Note|This step is currently being done automatically by the installer script.}}<br />
<br />
=== Step 4: Gemsets and Apps ===<br />
<br />
For each Rails application you should have a gemset. Suppose that you want to try [http://refinerycms.com RefineryCMS] against [http://www.browsercms.org BrowserCMS], two open-source Content Management Systems based on Rails.<br />
<br />
Install RefineryCMS first:<br />
<br />
$ rvm use 2.0.0@refinery --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install refinerycms refinerycms-i18n sqlite3<br />
<br />
Deploy a RefineryCMS instance called ''refineria'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo refinerycms refineria<br />
<br />
Install BrowserCMS in a different gemset:<br />
<br />
$ rvm use 2.0.0@browser --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install browsercms sqlite3<br />
<br />
Deploy a BrowserCMS instance called ''navegador'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo browsercms demo navegador<br />
$ cd /srv/http/navegador<br />
$ rvmsudo rake db:install<br />
<br />
=== Passenger for Nginx and Passenger Standalone ===<br />
<br />
Observe that the passenger gem was installed three times and with different intentions; in the environments<br />
* ''2.0.0'' => for Nginx,<br />
* ''2.0.0@refinery'' => Standalone<br />
* ''2.0.0@browser'' => Standalone<br />
<br />
The strategy is to combine Passenger for Nginx with Passenger Standalone. One must first identify the Ruby environment (interpreter plus gemset) that one uses the most; in this setup the Ruby interpreter and the default gemset were selected. One then proceeds with setting up Passenger for Nginx to use that environment (step 3).<br />
* Applications within the chosen environment can be served as in [[#Apache.2FNginx .28using Phusion Passenger.29|Apache/Nginx (using Phusion Passenger)]], page up in this article.<br />
* All applications that are to use a different Ruby version and/or gemset can be served separately through Passenger Standalone and hook into the main web server via a reverse proxy configuration (step 6).<br />
<br />
=== Step 5: .rvmrc files and ownerships ===<br />
<br />
This step is crucial for the correct behaviour of the setup. RVM seeks for .rvmrc files when changing folders; if it finds one, it reads it. In these files normally one stores a line like<br />
rvm <ruby_version>@<gemset_name><br />
so the specified environment is set at the entrance of applications' root folder.<br />
<br />
Create /srv/http/refineria/.rvmrc doing<br />
# echo "rvm ree@refinery" > /srv/http/refineria/.rvmrc<br />
, and /srv/http/navegador/.rvmrc with<br />
# echo "rvm 2.0.0@browser" > /srv/http/navegador/.rvmrc<br />
You have to enter to both application root folders now, because every first time that RVM finds a .rvmrc it asks you if you trust the given file, consequently you must validate the two files you have just created.<br />
<br />
These files aid the programs involved to find the correct gems.<br />
<br />
Apart, if applications' files and folders are not owned by the right user you will face database write-access problems. The use of rvmsudo produces ''root''-owned archives when generated by Rails; in the other hand, ''nobody'' is the user for Passenger —if you have not changed it—: who will use and should posses them. Fix this doing<br />
# chown -R nobody.nobody /srv/http/refineria /srv/http/navegador<br />
<br />
=== Step 6: Reverse proxies ===<br />
<br />
You have to start the Passenger Standalone web servers for your applications. So, do<br />
$ cd /srv/http/refineria<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
and<br />
$ cd /srv/http/navegador<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
. The first time that you run a Passenger Standalone it will perform a minor installation.<br />
<br />
Note that you are using ''unix domain'' sockets instead of the commonly-used ''TCP'' sockets; it turns out that unix domain are significantly faster than TCP sockets.<br />
<br />
{{note|If you are experimenting trouble with unix sockets, changing to TCP should work:<br />
rvmsudo passenger start -a 127.0.0.1 -p 3000 -d<br />
}}<br />
<br />
==== Launch Passenger Standalone daemons at system start-up ====<br />
<br />
''Do you have a script? Please post it here.''<br />
<br />
The systemd script below was made for a Typo blog I host at /srv/http/typo. It is located at /etc/systemd/system/passenger_typo.service. I set the Environment= tags (see "man systemd.exec") from the output of "rvm env". The only exception was PATH=, which I had to combine from my regular PATH and the output of rvm env.<br />
<br />
Note: If you do not set the "WorkingDirectory=" variable to your application folder, passenger will fail to find your app and will subsequently shut itself down.<br />
<br />
<pre><br />
[Unit]<br />
Description=Passenger Standalone Script for Typo<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
WorkingDirectory=/srv/http/typo<br />
PIDFile=/srv/http/typo/tmp/pids/passenger.pid<br />
<br />
Environment=PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo/bin:/usr/local/rvm/gems/ruby-2.0.0-p0@global/bin:/usr/local/rvm/rubies/ruby-2.0.0-p0/bin:/usr/local/rvm/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/bin/core_perl<br />
Environment=rvm_env_string=ruby-2.0.0-p0@typo<br />
Environment=rvm_path=/usr/local/rvm<br />
Environment=rvm_ruby_string=ruby-2.0.0-p0<br />
Environment=rvm_gemset_name=typo<br />
Environment=RUBY_VERSION=ruby-2.0.0-p0<br />
Environment=GEM_HOME=/usr/local/rvm/gems/ruby-2.0.0-p0@typo<br />
Environment=GEM_PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo:/usr/local/rvm/gems/ruby-2.0.0-p0@global<br />
Environment=MY_RUBY_HOME=/usr/local/rvm/rubies/ruby-2.0.0-p0<br />
Environment=IRBRC=/usr/local/rvm/rubies/ruby-2.0.0-p0/.irbrc<br />
<br />
ExecStart=/bin/bash -c "rvmsudo passenger start --socket /srv/http/typo/tmp/sockets/passenger.socket -d"<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
</pre><br />
<br />
=== Step 7: Deployment ===<br />
<br />
==== With subdomains ====<br />
<br />
Once again edit /opt/nginx/conf/nginx.conf to include some vital instructions:<br />
<br />
<pre><br />
## RefineryCMS ##<br />
<br />
server {<br />
server_name refinery.domain.com;<br />
root /srv/http/refineria/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/refineria/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
<br />
## BrowserCMS ##<br />
<br />
server {<br />
server_name browser.domain.com;<br />
root /srv/http/navegador/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/navegador/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
{{note|Or if using TCP sockets, configure the ''proxy_pass'' directive like<br />
<pre>proxy_pass http://127.0.0.1:3000;</pre><br />
}}<br />
<br />
==== Without subdomains ====<br />
<br />
If you for some reason do not want to host each application on its own subdomain but rather in a url like: {{ic|site.com/railsapp}} then you could do something like this in your config:<br />
<br />
<pre><br />
server {<br />
server_name site.com;<br />
#Base for the html files etc<br />
root /srv/http/;<br />
<br />
#First application you want hosted under domain site.com/railsapp<br />
location /railsapp {<br />
root /srv/http/railsapp/public;<br />
#you may need to change passenger_base_uri to be the uri you want to point at, ie:<br />
#passenger_base_uri /railsapp;<br />
#but probably only if you are using the other solution with passenger phusion<br />
proxy_pass http://unix:/srv/http/railsapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
<br />
#Second applicatino you want hosted under domain site.com/anotherapp<br />
location /anotherapp {<br />
root /srv/http/anotherapp/public;<br />
#same thing about the passenger_base_uri here, but with value /anotherapp instead<br />
proxy_pass http://unix:/srv/http/anotherapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
At this point you are in conditions to run Nginx with:<br />
<br />
# systemctl start nginx<br />
<br />
and to access both CMSs through ''refinery.domain.com'' and ''browser.domain.com''.<br />
<br />
=== References ===<br />
<br />
* http://beginrescueend.com/integration/passenger<br />
* http://blog.phusion.nl/2010/09/21/phusion-passenger-running-multiple-ruby-versions<br />
* http://www.ruby-journal.com/how-to-setup-rails-app-with-puma-and-nginx/<br />
* https://www.digitalocean.com/community/tutorials/how-to-deploy-a-rails-app-with-puma-and-nginx-on-ubuntu-14-04<br />
<br />
== See also ==<br />
<br />
* [[Ruby]]<br />
* [[Nginx]]<br />
* [[LAMP]]<br />
* [[MySQL]]<br />
<br />
== References ==<br />
<br />
* Ruby on Rails http://rubyonrails.org/download.<br />
* Mongrel http://mongrel.rubyforge.org.</div>Stbinanhttps://wiki.archlinux.org/index.php?title=Ruby_on_Rails&diff=394424Ruby on Rails2015-08-29T06:28:59Z<p>Stbinan: /* Option 2: by systemd */</p>
<hr />
<div>[[Category:Web server]]<br />
[[ja:Ruby on Rails]]<br />
[[zh-CN:Ruby on Rails]]<br />
[http://rubyonrails.org/ Ruby on Rails], often shortened to Rails or RoR, is an open source web application framework for the Ruby programming language. It is intended to be used with an Agile development methodology that is used by web developers for rapid development.<br />
<br />
This document describes how to set up the Ruby on Rails Framework on an Arch Linux system.<br />
<br />
== Installation ==<br />
<br />
Ruby on Rails requires [[Ruby]] to be installed, so read that article first for installation instructions. The {{pkg|nodejs}} package is also required.<br />
<br />
Ruby on Rails itself can be installed multiple ways:<br />
<br />
=== Option A: via RubyGems ===<br />
<br />
{{Note|You can also install Rails system-wide using Gems. To do this, run the following commands as root and append them with {{ic|--no-user-install}}. Please read [[Ruby#Installing gems per-user or system-wide]] for possible dangers of using RubyGem in this way.}}<br />
<br />
The following command will install Rails for the current user:<br />
$ gem install rails<br />
<br />
Building the documentation takes a while. If you want to skip it, append {{ic|--no-document}} to the install command.<br />
$ gem install rails --no-document<br />
<br />
gem is a package manager for Ruby modules, somewhat like pacman is to Arch Linux. To update your gems, simply run:<br />
$ gem update<br />
<br />
=== Option B: via pacgem ===<br />
<br />
You can install Rails using {{AUR|pacgem}}{{Broken package link|{{aur-mirror|pacgem}}}} from the [[AUR]]. Pacgem automatically creates PKGBUILDs and Arch packages for each of the gems. These packages will then be installed using pacman.<br />
# pacgem rails<br />
<br />
The gem packages can be updated with<br />
# pacgem -u<br />
<br />
=== Option C: from the AUR ===<br />
<br />
{{Warning|This is not recommended, as this might not include the latest Rails version, and additional dependencies may be introduced that may require you to run {{Ic|gem install}} anyway.}}<br />
<br />
There is a {{AUR|ruby-rails}} package available in the [[AUR]].<br />
<br />
=== Option D: from Quarry binary repository ===<br />
<br />
[[pacman|Install]] ''ruby-rails'' from the unofficial [[Unofficial user repositories#quarry|quarry]] repository.<br />
<br />
== Configuration ==<br />
<br />
Rails is bundled with a basic HTTP server called WeBrick. You can create a test application to test it. First, create an application with the rails command:<br />
<br />
$ rails new testapp_name<br />
<br />
{{Note|If you get an error like {{ic|Errno::ENOENT: No such file or directory (...) An error occurred while installing x, and Bundler cannot continue.}}, you might have to configure [[Ruby#Bundler|Bundler]] so that it installs gems per-user and not system-wide. Alternatively, run {{ic|# rails new testapp_name}} once as root. If it has completed successfully, delete {{ic|testapp_name/}} and run {{ic|$ rails new testapp_name}} again as a regular user.}}<br />
{{Note|If you get an error message like this:<br />
{{ic|... FetchError: SSL_connect returned&#61;1 errno&#61; 0 state&#61;SSLv2/v3 read server hello A: sslv3 alert handshake<br />
failure <nowiki>(https://s3.amazonaws.com/ production.s3.rubygems.org/gems/rake-10.0.3.gem)</nowiki> }}<br />
install {{Pkg|nodejs}} and try again.}}<br />
<br />
This creates a new folder inside your current working directory. <br />
<br />
$ cd testapp_name<br />
<br />
Next start the web server. It listens on port 3000 by default:<br />
<br />
$ rails server<br />
<br />
Now visit the testapp_name website on your local machine by opening <nowiki>http://localhost:3000</nowiki> in your browser<br />
{{Note|If Ruby complains about not being able to find a JavaScript runtime, install {{Pkg|nodejs}}.}}<br />
<br />
A test-page should shown greeting you "Welcome aboard".<br />
<br />
== Application servers ==<br />
<br />
The built-in Ruby On Rails HTTP server (WeBrick) is convenient for basic development, but it is not recommended for production use. Instead, you should use an application server such as [[#Thin]], [[#Unicorn]] or [[#Apache/Nginx (using Phusion Passenger)|Phusion Passenger]].<br />
<br />
=== Thin ===<br />
<br />
[http://code.macournoyer.com/thin/ Thin] is a fast and very simple Ruby web server.<br />
<br />
First install thin gem:<br />
$ gem install thin<br />
<br />
Then start it using:<br />
$ thin start<br />
<br />
=== Unicorn ===<br />
<br />
Unicorn is an application server that cannot talk directly to clients. Instead, a web server must sit between clients and Unicorn, proxying requests as needed. [http://unicorn.bogomips.org/ Unicorn] is loosely based on Mongrel. It is used by Github, and it uses an architecture that tries hard to find the best child for handling a request. [https://github.com/blog/517-unicorn Explanation of differences between Unicorn and Mongrel].<br />
<br />
Install the Unicorn gem:<br />
# gem install unicorn<br />
<br />
Then create a configuration file for your application in {{ic|/etc/unicorn/}}. For example; here is a configuration example (Based on [http://www.warden.pl/2011/01/07/running-redmine-under-unicorn-in-debian/]) for Redmine:<br />
<br />
{{hc|/etc/unicorn/redmine.ru|<nowiki><br />
working_directory "/srv/http/redmine"<br />
pid "/tmp/redmine.pid"<br />
<br />
preload_app true<br />
timeout 60<br />
worker_processes 4<br />
listen 4000<br />
stderr_path('/var/log/unicorn.log')<br />
<br />
GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true<br />
<br />
after_fork do |server, worker|<br />
#start the worker on port 4000, 4001, 4002 etc...<br />
addr = "0.0.0.0:#{4000 + worker.nr}"<br />
# infinite tries to start the worker<br />
server.listen(addr, :tries => -1, :delay => -1, :backlog => 128)<br />
<br />
#Drop privileges if running as root<br />
worker.user('nobody', 'nobody') if Process.euid == 0<br />
end<br />
</nowiki>}}<br />
<br />
Start it using:<br />
# /usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
==== Systemd service ====<br />
<br />
Put the following contents in {{ic|/etc/systemd/system/unicorn.service}}:<br />
{{hc|/etc/systemd/system/unicorn.service|2=<br />
[Unit]<br />
Description=Unicorn application server<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
User=redmine<br />
ExecStart=/usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
}}<br />
<br />
You can now easily start and stop unicorn using systemctl<br />
<br />
==== Nginx Configuration ====<br />
<br />
After setting up [[Nginx]], configure unicorn as an upstream server using something like this (Warning: this is a stripped example. It probably does not work without additional configuration):<br />
{{bc|1=<br />
http {<br />
upstream unicorn {<br />
server 127.0.0.1:4000 fail_timeout=0;<br />
server 127.0.0.1:4001 fail_timeout=0;<br />
server 127.0.0.1:4002 fail_timeout=0;<br />
server 127.0.0.1:4003 fail_timeout=0;<br />
}<br />
<br />
server {<br />
listen 80 default;<br />
server_name YOURHOSTNAMEHERE;<br />
<br />
location / {<br />
root /srv/http/redmine/public;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
proxy_pass http://unicorn;<br />
}<br />
}<br />
}<br />
}}<br />
<br />
=== Apache/Nginx (using Phusion Passenger) ===<br />
<br />
[http://www.modrails.com/ Passenger] also known as {{ic|mod_rails}} is a module available for [[Nginx]] and [[Apache]], that greatly simplifies setting up a Rails server environment. Nginx does not support modules as Apache and has to be compiled with {{ic|mod_rails}} in order to support Passenger; let Passenger compile it for you. As for Apache, let Passenger set up the module for you.<br />
<br />
Start by installing the 'passenger' gem:<br />
# gem install passenger<br />
<br />
If you are aiming to use [[Apache]], run:<br />
# passenger-install-apache2-module<br />
<br />
In case a rails application is deployed with a sub-URI, like http://example.com/yourapplication, some additional configuration is required, see [http://www.modrails.com/documentation/Users%20guide%20Apache.html#deploying_rails_to_sub_uri the modrails documentation]<br />
<br />
For [[Nginx]]:<br />
# passenger-install-nginx-module<br />
<br />
The installer will provide you with any additional information regarding the installation (such as installing additional libraries).<br />
<br />
To serve an application with Nginx, configure it as follows:<br />
<pre><br />
server {<br />
server_name app.example.org;<br />
root path_to_app/public; # Be sure to point to 'public' folder!<br />
passenger_enabled on;<br />
rails_env development; # Rails environment.<br />
}<br />
</pre><br />
<br />
=== Puma (with Nginx as reverse proxy server) ===<br />
<br />
[http://puma.io/ Puma] ([https://github.com/puma/puma Github Page]) is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications, and is considered the replacement for Webrick and Mongrel. It was designed to be the go-to server for Rubinius, but also works well with JRuby and MRI. While reverse proxy server would acts as a load balancer that routes all external requests to a pool of web apps.<br />
<br />
For a webserver it is better to use a server user and group, check [[Users_and_groups#Example_adding_a_user]], below use {{ic|rails}} as user name and {{ic|server}} as group name, also {{ic|my_app}} as rails app name.<br />
<br />
Start by copying your app to /var/www/my_app. And set new ownership with<br />
# cd /var/www/<br />
# chown -R rails:server my_app<br />
<br />
and permission for user with<br />
# chmod -R 775 my_app<br />
<br />
Then add {{ic|puma gem}} in the Gemfile and install with<br />
$ cd my_app <br />
$ bundle install<br />
<br />
Also install {{ic|nginx}} by pacman.<br />
<br />
Under your app folder, create sockets, pid and log folder with<br />
$ mkdir -p shared/pids shared/sockets shared/log<br />
<br />
Backup nginx.conf with<br />
# cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup<br />
<br />
Then create a new nginx.conf file with your favorite editor, copy codes below and modify as you like:<br />
<pre><br />
#user html;<br />
worker_processes 1; # this may connect with the worker numbers puma can use.<br />
<br />
#error_log logs/error.log;<br />
#error_log logs/error.log notice;<br />
#error_log logs/error.log info;<br />
<br />
#pid logs/nginx.pid;<br />
<br />
<br />
events {<br />
worker_connections 1024;<br />
}<br />
<br />
http {<br />
upstream app {<br />
# Path to Puma SOCK file, as defined previously<br />
server unix:/var/www/my_app/shared/sockets/puma.sock;<br />
}<br />
<br />
server {<br />
listen 80;<br />
server_name localhost; # or your server name<br />
<br />
root /var/www/my_app/public;<br />
<br />
try_files $uri/index.html $uri @app;<br />
<br />
location @app {<br />
proxy_pass http://app;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
}<br />
<br />
error_page 500 502 503 504 /500.html;<br />
client_max_body_size 4G;<br />
keepalive_timeout 10;<br />
}<br />
}</pre><br />
<br />
Start nginx service with<br />
# systemctl start nginx<br />
<br />
<br />
There are several ways to start puma server, two ways are recommended below:<br />
<br />
==== Option A: With config file ====<br />
<br />
Create file {{ic|config/puma.rb}}, copy codes below and modify as you like:<br />
<pre><br />
# Change to match your CPU core count<br />
# You can check available worker numbers with $ grep -c processor /proc/cpuinfo<br />
# also see the comment in the nginx.conf<br />
workers 2<br />
<br />
# Min and Max threads per worker<br />
#threads 1, 6<br />
<br />
app_dir = File.expand_path("../..", __FILE__)<br />
shared_dir = "#{app_dir}/shared"<br />
<br />
# Default to production<br />
#rails_env = ENV['RAILS_ENV'] || "production"<br />
#environment rails_env<br />
<br />
# Set up socket location<br />
bind "unix://#{shared_dir}/sockets/puma.sock"<br />
<br />
# Logging<br />
#stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true<br />
<br />
# Set master PID and state locations<br />
pidfile "#{shared_dir}/pids/puma.pid"<br />
#state_path "#{shared_dir}/pids/puma.state"<br />
#activate_control_app<br />
<br />
#on_worker_boot do<br />
# require "active_record"<br />
# ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished<br />
# ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])<br />
#end</pre><br />
<br />
and start server with<br />
$ bundle exec puma -C config/puma.rb<br />
<br />
You can also run it in background with parameter {{ic|-d}} and check with<br />
$ ps aux| grep puma<br />
when you want to {{ic|kill}} it.<br />
<br />
==== Option 2: by systemd ====<br />
<br />
Create a new systemd unit {{ic|puma.service}} under ~/.config/systemd/user/ and copy codes below<br />
<pre><br />
[Unit]<br />
Description=Puma application server<br />
After=network.target<br />
<br />
[Service]<br />
WorkingDirectory=/var/www/my_app<br />
#Environment=RAILS_ENV=production<br />
#User=rails<br />
PIDFile=/var/www/my_app/shared/pids/puma.pid<br />
ExecStart=/home/rails/.gem/ruby/2.2.0/bin/bundle exec \<br />
/home/rails/.gem/ruby/2.2.0/bin/puma \<br />
-b unix:///var/www/my_app/shared/sockets/puma.sock \<br />
--pidfile /var/www/my_app/shared/pids/puma.pid<br />
<br />
[Install]<br />
WantedBy=multi-user.target</pre><br />
<br />
Hint: For ExecStart, if you install gem globally, you can check route /usr/local/bin/, and also reference the execution code in Option 1.<br />
<br />
Then start puma with<br />
$ systemctl --user start puma<br />
<br />
For further reading take a look at [[Ruby_on_Rails#References]]<br />
<br />
== Databases ==<br />
<br />
Most web applications will need to interact with some sort of database. ActiveRecord (the ORM used by Rails to provide database abstraction) supports several database vendors, the most popular of which are MySQL, SQLite, and PostgreSQL.<br />
<br />
=== SQLite ===<br />
<br />
SQLite is the default lightweight database for Ruby on Rails. To enable SQLite, simply install {{Pkg|sqlite}}.<br />
<br />
=== PostgreSQL ===<br />
<br />
Install {{Pkg|postgresql}}.<br />
<br />
=== MySQL ===<br />
<br />
First, install and configure a MySQL server. Please refer to [[MySQL]] on how to do this.<br />
<br />
A gem with some native extensions is required, probably best installed as root:<br />
# gem install mysql<br />
<br />
You can generate a rails application configured for MySQL by using the {{ic|-d}} parameter:<br />
$ rails new testapp_name -d mysql<br />
<br />
You then need to edit {{ic|config/database.yml}}. Rails uses different databases for development, testing, production and other environments. Here is an example development configuration for MySQL running on localhost:<br />
<br />
development:<br />
adapter: mysql<br />
database: my_application_database<br />
username: development<br />
password: my_secret_password<br />
<br />
Note that you do not have to actually create the database using MySQL, as this can be done via Rails with:<br />
# rake db:create<br />
<br />
If no errors are shown, then your database has been created and Rails can talk to your MySQL database.<br />
<br />
== The Perfect Rails Setup ==<br />
<br />
''Phusion Passenger running multiple Ruby versions.''<br />
<br />
* [https://www.archlinux.org/ Arch Linux]: A simple, lightweight distribution. ;)<br />
* [http://www.nginx.org/ Nginx]: A fast and lightweight '''web server''' with a strong focus on high concurrency, performance and low memory usage.<br />
* [http://www.modrails.com/ Passenger] (a.k.a. mod_rails or mod_rack): Supports both Apache and Nginx web servers. It makes deployment of Ruby web applications, such as those built on Ruby on Rails web framework, a breeze.<br />
* [https://rvm.io/ Ruby Version Manager] (RVM): A command-line tool which allows you to easily install, manage, and work with multiple Ruby environments from interpreters to sets of gems. RVM lets you deploy each project with its own completely self-contained and dedicated environment —from the specific version of ruby, all the way down to the precise set of required gems to run your application—.<br />
* [http://sqlite.org/ SQLite]: The default lightweight '''database''' for Ruby on Rails.<br />
<br />
=== Step 0: SQLite ===<br />
<br />
Install {{Pkg|sqlite}}.<br />
<br />
{{note|Of course SQLite is not critical in this setup, you can use MySQL and PostgreSQL as well.}}<br />
<br />
=== Step 1: RVM ===<br />
<br />
Make a multi-user [[RVM]] installation as specified [[RVM#Multi-user_installation|here]].<br />
<br />
In the 'adding users to the rvm group' step, do<br />
# usermod -a -G rvm http<br />
# usermod -a -G rvm nobody<br />
<br />
{{ic|http}} and {{ic|nobody}} are the users related to Nginx and Passenger, respectively.<br />
<br />
{{note|Maybe adding the 'nobody' user to the 'rvm' group is not necessary.}}<br />
<br />
=== Step 2: Rubies ===<br />
<br />
Once you have a working RVM installation in your hands, it is time to install the latest Ruby interpreter<br />
{{Note|During the installation of Ruby patches will be applied. Consider installing the {{ic|base-devel}} group beforehand.}}<br />
<br />
$ rvm install 2.0.0<br />
<br />
{{Note| It may be useful to delete the 'global' gemsets of the environments that have web applications. Their gems might somehow interfere with Passenger. In that case, a {{ic|rvm 2.0.0 do gemset delete global}} is sufficient.}}<br />
<br />
=== Step 3: Nginx with Passenger support ===<br />
<br />
Run the following to allow passenger install nginx:<br />
$ rvm use 2.0.0 <br />
$ gem install passenger<br />
$ rvmsudo passenger-install-nginx-module<br />
<br />
The passenger gem will be put into the ''default'' gemset.<br />
<br />
This will download the sources of Nginx, compile and install it for you. It will guide you through all the process. Note that the default location for Nginx will be {{ic|/opt/nginx}}.<br />
<br />
{{Note|If you encounter a compilation error regarding Boost threads, see [https://bbs.archlinux.org/viewtopic.php?id&#61;139164 this] article.}}<br />
<br />
After completion, add the following two lines into the 'http block' at {{ic|/opt/nginx/conf/nginx.conf}} that look like:<br />
<br />
http { <br />
...<br />
passenger_root /usr/local/rvm/gems/ruby-2.0.0-p353/gems/passenger-3.0.9;<br />
passenger_ruby /usr/local/rvm/wrappers/ruby-2.0.0-p353/ruby;<br />
...<br />
}<br />
<br />
{{Note|This step is currently being done automatically by the installer script.}}<br />
<br />
=== Step 4: Gemsets and Apps ===<br />
<br />
For each Rails application you should have a gemset. Suppose that you want to try [http://refinerycms.com RefineryCMS] against [http://www.browsercms.org BrowserCMS], two open-source Content Management Systems based on Rails.<br />
<br />
Install RefineryCMS first:<br />
<br />
$ rvm use 2.0.0@refinery --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install refinerycms refinerycms-i18n sqlite3<br />
<br />
Deploy a RefineryCMS instance called ''refineria'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo refinerycms refineria<br />
<br />
Install BrowserCMS in a different gemset:<br />
<br />
$ rvm use 2.0.0@browser --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install browsercms sqlite3<br />
<br />
Deploy a BrowserCMS instance called ''navegador'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo browsercms demo navegador<br />
$ cd /srv/http/navegador<br />
$ rvmsudo rake db:install<br />
<br />
=== Passenger for Nginx and Passenger Standalone ===<br />
<br />
Observe that the passenger gem was installed three times and with different intentions; in the environments<br />
* ''2.0.0'' => for Nginx,<br />
* ''2.0.0@refinery'' => Standalone<br />
* ''2.0.0@browser'' => Standalone<br />
<br />
The strategy is to combine Passenger for Nginx with Passenger Standalone. One must first identify the Ruby environment (interpreter plus gemset) that one uses the most; in this setup the Ruby interpreter and the default gemset were selected. One then proceeds with setting up Passenger for Nginx to use that environment (step 3).<br />
* Applications within the chosen environment can be served as in [[#Apache.2FNginx .28using Phusion Passenger.29|Apache/Nginx (using Phusion Passenger)]], page up in this article.<br />
* All applications that are to use a different Ruby version and/or gemset can be served separately through Passenger Standalone and hook into the main web server via a reverse proxy configuration (step 6).<br />
<br />
=== Step 5: .rvmrc files and ownerships ===<br />
<br />
This step is crucial for the correct behaviour of the setup. RVM seeks for .rvmrc files when changing folders; if it finds one, it reads it. In these files normally one stores a line like<br />
rvm <ruby_version>@<gemset_name><br />
so the specified environment is set at the entrance of applications' root folder.<br />
<br />
Create /srv/http/refineria/.rvmrc doing<br />
# echo "rvm ree@refinery" > /srv/http/refineria/.rvmrc<br />
, and /srv/http/navegador/.rvmrc with<br />
# echo "rvm 2.0.0@browser" > /srv/http/navegador/.rvmrc<br />
You have to enter to both application root folders now, because every first time that RVM finds a .rvmrc it asks you if you trust the given file, consequently you must validate the two files you have just created.<br />
<br />
These files aid the programs involved to find the correct gems.<br />
<br />
Apart, if applications' files and folders are not owned by the right user you will face database write-access problems. The use of rvmsudo produces ''root''-owned archives when generated by Rails; in the other hand, ''nobody'' is the user for Passenger —if you have not changed it—: who will use and should posses them. Fix this doing<br />
# chown -R nobody.nobody /srv/http/refineria /srv/http/navegador<br />
<br />
=== Step 6: Reverse proxies ===<br />
<br />
You have to start the Passenger Standalone web servers for your applications. So, do<br />
$ cd /srv/http/refineria<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
and<br />
$ cd /srv/http/navegador<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
. The first time that you run a Passenger Standalone it will perform a minor installation.<br />
<br />
Note that you are using ''unix domain'' sockets instead of the commonly-used ''TCP'' sockets; it turns out that unix domain are significantly faster than TCP sockets.<br />
<br />
{{note|If you are experimenting trouble with unix sockets, changing to TCP should work:<br />
rvmsudo passenger start -a 127.0.0.1 -p 3000 -d<br />
}}<br />
<br />
==== Launch Passenger Standalone daemons at system start-up ====<br />
<br />
''Do you have a script? Please post it here.''<br />
<br />
The systemd script below was made for a Typo blog I host at /srv/http/typo. It is located at /etc/systemd/system/passenger_typo.service. I set the Environment= tags (see "man systemd.exec") from the output of "rvm env". The only exception was PATH=, which I had to combine from my regular PATH and the output of rvm env.<br />
<br />
Note: If you do not set the "WorkingDirectory=" variable to your application folder, passenger will fail to find your app and will subsequently shut itself down.<br />
<br />
<pre><br />
[Unit]<br />
Description=Passenger Standalone Script for Typo<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
WorkingDirectory=/srv/http/typo<br />
PIDFile=/srv/http/typo/tmp/pids/passenger.pid<br />
<br />
Environment=PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo/bin:/usr/local/rvm/gems/ruby-2.0.0-p0@global/bin:/usr/local/rvm/rubies/ruby-2.0.0-p0/bin:/usr/local/rvm/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/bin/core_perl<br />
Environment=rvm_env_string=ruby-2.0.0-p0@typo<br />
Environment=rvm_path=/usr/local/rvm<br />
Environment=rvm_ruby_string=ruby-2.0.0-p0<br />
Environment=rvm_gemset_name=typo<br />
Environment=RUBY_VERSION=ruby-2.0.0-p0<br />
Environment=GEM_HOME=/usr/local/rvm/gems/ruby-2.0.0-p0@typo<br />
Environment=GEM_PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo:/usr/local/rvm/gems/ruby-2.0.0-p0@global<br />
Environment=MY_RUBY_HOME=/usr/local/rvm/rubies/ruby-2.0.0-p0<br />
Environment=IRBRC=/usr/local/rvm/rubies/ruby-2.0.0-p0/.irbrc<br />
<br />
ExecStart=/bin/bash -c "rvmsudo passenger start --socket /srv/http/typo/tmp/sockets/passenger.socket -d"<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
</pre><br />
<br />
=== Step 7: Deployment ===<br />
<br />
==== With subdomains ====<br />
<br />
Once again edit /opt/nginx/conf/nginx.conf to include some vital instructions:<br />
<br />
<pre><br />
## RefineryCMS ##<br />
<br />
server {<br />
server_name refinery.domain.com;<br />
root /srv/http/refineria/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/refineria/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
<br />
## BrowserCMS ##<br />
<br />
server {<br />
server_name browser.domain.com;<br />
root /srv/http/navegador/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/navegador/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
{{note|Or if using TCP sockets, configure the ''proxy_pass'' directive like<br />
<pre>proxy_pass http://127.0.0.1:3000;</pre><br />
}}<br />
<br />
==== Without subdomains ====<br />
<br />
If you for some reason do not want to host each application on its own subdomain but rather in a url like: {{ic|site.com/railsapp}} then you could do something like this in your config:<br />
<br />
<pre><br />
server {<br />
server_name site.com;<br />
#Base for the html files etc<br />
root /srv/http/;<br />
<br />
#First application you want hosted under domain site.com/railsapp<br />
location /railsapp {<br />
root /srv/http/railsapp/public;<br />
#you may need to change passenger_base_uri to be the uri you want to point at, ie:<br />
#passenger_base_uri /railsapp;<br />
#but probably only if you are using the other solution with passenger phusion<br />
proxy_pass http://unix:/srv/http/railsapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
<br />
#Second applicatino you want hosted under domain site.com/anotherapp<br />
location /anotherapp {<br />
root /srv/http/anotherapp/public;<br />
#same thing about the passenger_base_uri here, but with value /anotherapp instead<br />
proxy_pass http://unix:/srv/http/anotherapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
At this point you are in conditions to run Nginx with:<br />
<br />
# systemctl start nginx<br />
<br />
and to access both CMSs through ''refinery.domain.com'' and ''browser.domain.com''.<br />
<br />
=== References ===<br />
<br />
* http://beginrescueend.com/integration/passenger<br />
* http://blog.phusion.nl/2010/09/21/phusion-passenger-running-multiple-ruby-versions<br />
* http://www.ruby-journal.com/how-to-setup-rails-app-with-puma-and-nginx/<br />
* https://www.digitalocean.com/community/tutorials/how-to-deploy-a-rails-app-with-puma-and-nginx-on-ubuntu-14-04<br />
<br />
== See also ==<br />
<br />
* [[Ruby]]<br />
* [[Nginx]]<br />
* [[LAMP]]<br />
* [[MySQL]]<br />
<br />
== References ==<br />
<br />
* Ruby on Rails http://rubyonrails.org/download.<br />
* Mongrel http://mongrel.rubyforge.org.</div>Stbinanhttps://wiki.archlinux.org/index.php?title=Ruby_on_Rails&diff=391862Ruby on Rails2015-08-20T09:24:13Z<p>Stbinan: /* Puma (with Nginx as reverse proxy server) */</p>
<hr />
<div>[[Category:Web server]]<br />
[[zh-CN:Ruby on Rails]]<br />
[http://rubyonrails.org/ Ruby on Rails], often shortened to Rails or RoR, is an open source web application framework for the Ruby programming language. It is intended to be used with an Agile development methodology that is used by web developers for rapid development.<br />
<br />
This document describes how to set up the Ruby on Rails Framework on an Arch Linux system.<br />
<br />
== Installation ==<br />
<br />
Ruby on Rails requires [[Ruby]] to be installed, so read that article first for installation instructions. The {{pkg|nodejs}} package is also required.<br />
<br />
Ruby on Rails itself can be installed multiple ways:<br />
<br />
=== Option A: via RubyGems ===<br />
<br />
{{Note|You can also install Rails system-wide using Gems. To do this, run the following commands as root and append them with {{ic|--no-user-install}}. Please read [[Ruby#Installing gems per-user or system-wide]] for possible dangers of using RubyGem in this way.}}<br />
<br />
The following command will install Rails for the current user:<br />
$ gem install rails<br />
<br />
Building the documentation takes a while. If you want to skip it, append {{ic|--no-document}} to the install command.<br />
$ gem install rails --no-document<br />
<br />
gem is a package manager for Ruby modules, somewhat like pacman is to Arch Linux. To update your gems, simply run:<br />
$ gem update<br />
<br />
=== Option B: via pacgem ===<br />
<br />
You can install Rails using {{AUR|pacgem}} from the [[AUR]]. Pacgem automatically creates PKGBUILDs and Arch packages for each of the gems. These packages will then be installed using pacman.<br />
# pacgem rails<br />
<br />
The gem packages can be updated with<br />
# pacgem -u<br />
<br />
=== Option C: from the AUR ===<br />
<br />
{{Warning|This is not recommended, as this might not include the latest Rails version, and additional dependencies may be introduced that may require you to run {{Ic|gem install}} anyway.}}<br />
<br />
There is a {{AUR|ruby-rails}} package available in the [[AUR]].<br />
<br />
=== Option D: from Quarry binary repository ===<br />
<br />
[[pacman|Install]] ''ruby-rails'' from the unofficial [[Unofficial user repositories#quarry|quarry]] repository.<br />
<br />
== Configuration ==<br />
<br />
Rails is bundled with a basic HTTP server called WeBrick. You can create a test application to test it. First, create an application with the rails command:<br />
<br />
$ rails new testapp_name<br />
<br />
{{Note|If you get an error like {{ic|Errno::ENOENT: No such file or directory (...) An error occurred while installing x, and Bundler cannot continue.}}, you might have to configure [[Ruby#Bundler|Bundler]] so that it installs gems per-user and not system-wide. Alternatively, run {{ic|# rails new testapp_name}} once as root. If it has completed successfully, delete {{ic|testapp_name/}} and run {{ic|$ rails new testapp_name}} again as a regular user.}}<br />
{{Note|If you get an error message like this:<br />
{{ic|... FetchError: SSL_connect returned&#61;1 errno&#61; 0 state&#61;SSLv2/v3 read server hello A: sslv3 alert handshake<br />
failure <nowiki>(https://s3.amazonaws.com/ production.s3.rubygems.org/gems/rake-10.0.3.gem)</nowiki> }}<br />
install {{Pkg|nodejs}} and try again.}}<br />
<br />
This creates a new folder inside your current working directory. <br />
<br />
$ cd testapp_name<br />
<br />
Next start the web server. It listens on port 3000 by default:<br />
<br />
$ rails server<br />
<br />
Now visit the testapp_name website on your local machine by opening <nowiki>http://localhost:3000</nowiki> in your browser<br />
{{Note|If Ruby complains about not being able to find a JavaScript runtime, install {{Pkg|nodejs}}.}}<br />
<br />
A test-page should shown greeting you "Welcome aboard".<br />
<br />
== Application servers ==<br />
<br />
The built-in Ruby On Rails HTTP server (WeBrick) is convenient for basic development, but it is not recommended for production use. Instead, you should use an application server such as [[#Thin]], [[#Unicorn]] or [[#Apache/Nginx (using Phusion Passenger)|Phusion Passenger]].<br />
<br />
=== Thin ===<br />
<br />
[http://code.macournoyer.com/thin/ Thin] is a fast and very simple Ruby web server.<br />
<br />
First install thin gem:<br />
$ gem install thin<br />
<br />
Then start it using:<br />
$ thin start<br />
<br />
=== Unicorn ===<br />
<br />
Unicorn is an application server that cannot talk directly to clients. Instead, a web server must sit between clients and Unicorn, proxying requests as needed. [http://unicorn.bogomips.org/ Unicorn] is loosely based on Mongrel. It is used by Github, and it uses an architecture that tries hard to find the best child for handling a request. [https://github.com/blog/517-unicorn Explanation of differences between Unicorn and Mongrel].<br />
<br />
Install the Unicorn gem:<br />
# gem install unicorn<br />
<br />
Then create a configuration file for your application in {{ic|/etc/unicorn/}}. For example; here is a configuration example (Based on [http://www.warden.pl/2011/01/07/running-redmine-under-unicorn-in-debian/]) for Redmine:<br />
<br />
{{hc|/etc/unicorn/redmine.ru|<nowiki><br />
working_directory "/srv/http/redmine"<br />
pid "/tmp/redmine.pid"<br />
<br />
preload_app true<br />
timeout 60<br />
worker_processes 4<br />
listen 4000<br />
stderr_path('/var/log/unicorn.log')<br />
<br />
GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true<br />
<br />
after_fork do |server, worker|<br />
#start the worker on port 4000, 4001, 4002 etc...<br />
addr = "0.0.0.0:#{4000 + worker.nr}"<br />
# infinite tries to start the worker<br />
server.listen(addr, :tries => -1, :delay => -1, :backlog => 128)<br />
<br />
#Drop privileges if running as root<br />
worker.user('nobody', 'nobody') if Process.euid == 0<br />
end<br />
</nowiki>}}<br />
<br />
Start it using:<br />
# /usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
==== Systemd service ====<br />
<br />
Put the following contents in {{ic|/etc/systemd/system/unicorn.service}}:<br />
{{hc|/etc/systemd/system/unicorn.service|2=<br />
[Unit]<br />
Description=Unicorn application server<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
User=redmine<br />
ExecStart=/usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
}}<br />
<br />
You can now easily start and stop unicorn using systemctl<br />
<br />
==== Nginx Configuration ====<br />
<br />
After setting up [[Nginx]], configure unicorn as an upstream server using something like this (Warning: this is a stripped example. It probably does not work without additional configuration):<br />
{{bc|1=<br />
http {<br />
upstream unicorn {<br />
server 127.0.0.1:4000 fail_timeout=0;<br />
server 127.0.0.1:4001 fail_timeout=0;<br />
server 127.0.0.1:4002 fail_timeout=0;<br />
server 127.0.0.1:4003 fail_timeout=0;<br />
}<br />
<br />
server {<br />
listen 80 default;<br />
server_name YOURHOSTNAMEHERE;<br />
<br />
location / {<br />
root /srv/http/redmine/public;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
proxy_pass http://unicorn;<br />
}<br />
}<br />
}<br />
}}<br />
<br />
=== Apache/Nginx (using Phusion Passenger) ===<br />
<br />
[http://www.modrails.com/ Passenger] also known as {{ic|mod_rails}} is a module available for [[Nginx]] and [[Apache]], that greatly simplifies setting up a Rails server environment. Nginx does not support modules as Apache and has to be compiled with {{ic|mod_rails}} in order to support Passenger; let Passenger compile it for you. As for Apache, let Passenger set up the module for you.<br />
<br />
Start by installing the 'passenger' gem:<br />
# gem install passenger<br />
<br />
If you are aiming to use [[Apache]], run:<br />
# passenger-install-apache2-module<br />
<br />
In case a rails application is deployed with a sub-URI, like http://example.com/yourapplication, some additional configuration is required, see [http://www.modrails.com/documentation/Users%20guide%20Apache.html#deploying_rails_to_sub_uri the modrails documentation]<br />
<br />
For [[Nginx]]:<br />
# passenger-install-nginx-module<br />
<br />
The installer will provide you with any additional information regarding the installation (such as installing additional libraries).<br />
<br />
To serve an application with Nginx, configure it as follows:<br />
<pre><br />
server {<br />
server_name app.example.org;<br />
root path_to_app/public; # Be sure to point to 'public' folder!<br />
passenger_enabled on;<br />
rails_env development; # Rails environment.<br />
}<br />
</pre><br />
<br />
=== Puma (with Nginx as reverse proxy server) ===<br />
<br />
[http://puma.io/ Puma] ([https://github.com/puma/puma Github Page]) is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications, and is considered the replacement for Webrick and Mongrel. It was designed to be the go-to server for Rubinius, but also works well with JRuby and MRI. While reverse proxy server would acts as a load balancer that routes all external requests to a pool of web apps.<br />
<br />
For a webserver it is better to use a server user and group, check [[Users_and_groups#Example_adding_a_user]], below use {{ic|rails}} as user name and {{ic|server}} as group name, also {{ic|my_app}} as rails app name.<br />
<br />
Start by copying your app to /var/www/my_app. And set new ownership with<br />
# cd /var/www/<br />
# chown -R rails:server my_app<br />
<br />
and permission for user with<br />
# chmod -R 775 my_app<br />
<br />
Then add {{ic|puma gem}} in the Gemfile and install with<br />
$ cd my_app <br />
$ bundle install<br />
<br />
Also install {{ic|nginx}} by pacman.<br />
<br />
Under your app folder, create sockets, pid and log folder with<br />
$ mkdir -p shared/pids shared/sockets shared/log<br />
<br />
Backup nginx.conf with<br />
# cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup<br />
<br />
Then create a new nginx.conf file with your favorite editor, copy codes below and modify as you like:<br />
<pre><br />
#user html;<br />
worker_processes 1; # this may connect with the worker numbers puma can use.<br />
<br />
#error_log logs/error.log;<br />
#error_log logs/error.log notice;<br />
#error_log logs/error.log info;<br />
<br />
#pid logs/nginx.pid;<br />
<br />
<br />
events {<br />
worker_connections 1024;<br />
}<br />
<br />
http {<br />
upstream app {<br />
# Path to Puma SOCK file, as defined previously<br />
server unix:/var/www/my_app/shared/sockets/puma.sock;<br />
}<br />
<br />
server {<br />
listen 80;<br />
server_name localhost; # or your server name<br />
<br />
root /var/www/my_app/public;<br />
<br />
try_files $uri/index.html $uri @app;<br />
<br />
location @app {<br />
proxy_pass http://app;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
}<br />
<br />
error_page 500 502 503 504 /500.html;<br />
client_max_body_size 4G;<br />
keepalive_timeout 10;<br />
}<br />
}</pre><br />
<br />
Start nginx service with<br />
# systemctl start nginx<br />
<br />
<br />
There are several ways to start puma server, two ways are recommended below:<br />
<br />
==== Option A: With config file ====<br />
<br />
Create file {{ic|config/puma.rb}}, copy codes below and modify as you like:<br />
<pre><br />
# Change to match your CPU core count<br />
# You can check available worker numbers with $ grep -c processor /proc/cpuinfo<br />
# also see the comment in the nginx.conf<br />
workers 2<br />
<br />
# Min and Max threads per worker<br />
#threads 1, 6<br />
<br />
app_dir = File.expand_path("../..", __FILE__)<br />
shared_dir = "#{app_dir}/shared"<br />
<br />
# Default to production<br />
#rails_env = ENV['RAILS_ENV'] || "production"<br />
#environment rails_env<br />
<br />
# Set up socket location<br />
bind "unix://#{shared_dir}/sockets/puma.sock"<br />
<br />
# Logging<br />
#stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true<br />
<br />
# Set master PID and state locations<br />
pidfile "#{shared_dir}/pids/puma.pid"<br />
#state_path "#{shared_dir}/pids/puma.state"<br />
#activate_control_app<br />
<br />
#on_worker_boot do<br />
# require "active_record"<br />
# ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished<br />
# ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])<br />
#end</pre><br />
<br />
and start server with<br />
$ bundle exec puma -C config/puma.rb<br />
<br />
You can also run it in background with parameter {{ic|-d}} and check with<br />
$ ps aux| grep puma<br />
when you want to {{ic|kill}} it.<br />
<br />
==== Option 2: by systemd ====<br />
<br />
Create a new systemd unit {{ic|puma.service}} under ~/.config/systemd/user/ and copy codes below<br />
<pre><br />
[Unit]<br />
Description=Puma application server<br />
After=network.target<br />
<br />
[Service]<br />
WorkingDirectory=/var/www/my_app<br />
#Environment=RAILS_ENV=production<br />
#User=rails<br />
PIDFile=/var/www/my_app/shared/pids/puma.pid<br />
ExecStart=/home/rails/.gem/ruby/2.2.0/bin/bundle exec \<br />
/home/rails/.gem/ruby/2.2.0/bin/puma \<br />
-b unix:///var/www/my_app/shared/sockets/puma.sock \<br />
--pidfile /var/www/my_app/shared/pids/puma.pid<br />
<br />
[Install]<br />
WantedBy=multi-user.target</pre><br />
<br />
Then start puma with<br />
$ systemctl --user start puma<br />
<br />
For further reading take a look at [[Ruby_on_Rails#References]]<br />
<br />
== Databases ==<br />
<br />
Most web applications will need to interact with some sort of database. ActiveRecord (the ORM used by Rails to provide database abstraction) supports several database vendors, the most popular of which are MySQL, SQLite, and PostgreSQL.<br />
<br />
=== SQLite ===<br />
<br />
SQLite is the default lightweight database for Ruby on Rails. To enable SQLite, simply install {{Pkg|sqlite}}.<br />
<br />
=== PostgreSQL ===<br />
<br />
Install {{Pkg|postgresql}}.<br />
<br />
=== MySQL ===<br />
<br />
First, install and configure a MySQL server. Please refer to [[MySQL]] on how to do this.<br />
<br />
A gem with some native extensions is required, probably best installed as root:<br />
# gem install mysql<br />
<br />
You can generate a rails application configured for MySQL by using the {{ic|-d}} parameter:<br />
$ rails new testapp_name -d mysql<br />
<br />
You then need to edit {{ic|config/database.yml}}. Rails uses different databases for development, testing, production and other environments. Here is an example development configuration for MySQL running on localhost:<br />
<br />
development:<br />
adapter: mysql<br />
database: my_application_database<br />
username: development<br />
password: my_secret_password<br />
<br />
Note that you do not have to actually create the database using MySQL, as this can be done via Rails with:<br />
# rake db:create<br />
<br />
If no errors are shown, then your database has been created and Rails can talk to your MySQL database.<br />
<br />
== The Perfect Rails Setup ==<br />
<br />
''Phusion Passenger running multiple Ruby versions.''<br />
<br />
* [https://www.archlinux.org/ Arch Linux]: A simple, lightweight distribution. ;)<br />
* [http://www.nginx.org/ Nginx]: A fast and lightweight '''web server''' with a strong focus on high concurrency, performance and low memory usage.<br />
* [http://www.modrails.com/ Passenger] (a.k.a. mod_rails or mod_rack): Supports both Apache and Nginx web servers. It makes deployment of Ruby web applications, such as those built on Ruby on Rails web framework, a breeze.<br />
* [https://rvm.io/ Ruby Version Manager] (RVM): A command-line tool which allows you to easily install, manage, and work with multiple Ruby environments from interpreters to sets of gems. RVM lets you deploy each project with its own completely self-contained and dedicated environment —from the specific version of ruby, all the way down to the precise set of required gems to run your application—.<br />
* [http://sqlite.org/ SQLite]: The default lightweight '''database''' for Ruby on Rails.<br />
<br />
=== Step 0: SQLite ===<br />
<br />
Install {{Pkg|sqlite}}.<br />
<br />
{{note|Of course SQLite is not critical in this setup, you can use MySQL and PostgreSQL as well.}}<br />
<br />
=== Step 1: RVM ===<br />
<br />
Make a multi-user [[RVM]] installation as specified [[RVM#Multi-user_installation|here]].<br />
<br />
In the 'adding users to the rvm group' step, do<br />
# usermod -a -G rvm http<br />
# usermod -a -G rvm nobody<br />
<br />
{{ic|http}} and {{ic|nobody}} are the users related to Nginx and Passenger, respectively.<br />
<br />
{{note|Maybe adding the 'nobody' user to the 'rvm' group is not necessary.}}<br />
<br />
=== Step 2: Rubies ===<br />
<br />
Once you have a working RVM installation in your hands, it is time to install the latest Ruby interpreter<br />
{{Note|During the installation of Ruby patches will be applied. Consider installing the {{ic|base-devel}} group beforehand.}}<br />
<br />
$ rvm install 2.0.0<br />
<br />
{{Note| It may be useful to delete the 'global' gemsets of the environments that have web applications. Their gems might somehow interfere with Passenger. In that case, a {{ic|rvm 2.0.0 do gemset delete global}} is sufficient.}}<br />
<br />
=== Step 3: Nginx with Passenger support ===<br />
<br />
Run the following to allow passenger install nginx:<br />
$ rvm use 2.0.0 <br />
$ gem install passenger<br />
$ rvmsudo passenger-install-nginx-module<br />
<br />
The passenger gem will be put into the ''default'' gemset.<br />
<br />
This will download the sources of Nginx, compile and install it for you. It will guide you through all the process. Note that the default location for Nginx will be {{ic|/opt/nginx}}.<br />
<br />
{{Note|If you encounter a compilation error regarding Boost threads, see [https://bbs.archlinux.org/viewtopic.php?id&#61;139164 this] article.}}<br />
<br />
After completion, add the following two lines into the 'http block' at {{ic|/opt/nginx/conf/nginx.conf}} that look like:<br />
<br />
http { <br />
...<br />
passenger_root /usr/local/rvm/gems/ruby-2.0.0-p353/gems/passenger-3.0.9;<br />
passenger_ruby /usr/local/rvm/wrappers/ruby-2.0.0-p353/ruby;<br />
...<br />
}<br />
<br />
{{Note|This step is currently being done automatically by the installer script.}}<br />
<br />
=== Step 4: Gemsets and Apps ===<br />
<br />
For each Rails application you should have a gemset. Suppose that you want to try [http://refinerycms.com RefineryCMS] against [http://www.browsercms.org BrowserCMS], two open-source Content Management Systems based on Rails.<br />
<br />
Install RefineryCMS first:<br />
<br />
$ rvm use 2.0.0@refinery --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install refinerycms refinerycms-i18n sqlite3<br />
<br />
Deploy a RefineryCMS instance called ''refineria'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo refinerycms refineria<br />
<br />
Install BrowserCMS in a different gemset:<br />
<br />
$ rvm use 2.0.0@browser --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install browsercms sqlite3<br />
<br />
Deploy a BrowserCMS instance called ''navegador'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo browsercms demo navegador<br />
$ cd /srv/http/navegador<br />
$ rvmsudo rake db:install<br />
<br />
=== Passenger for Nginx and Passenger Standalone ===<br />
<br />
Observe that the passenger gem was installed three times and with different intentions; in the environments<br />
* ''2.0.0'' => for Nginx,<br />
* ''2.0.0@refinery'' => Standalone<br />
* ''2.0.0@browser'' => Standalone<br />
<br />
The strategy is to combine Passenger for Nginx with Passenger Standalone. One must first identify the Ruby environment (interpreter plus gemset) that one uses the most; in this setup the Ruby interpreter and the default gemset were selected. One then proceeds with setting up Passenger for Nginx to use that environment (step 3).<br />
* Applications within the chosen environment can be served as in [[#Apache.2FNginx .28using Phusion Passenger.29|Apache/Nginx (using Phusion Passenger)]], page up in this article.<br />
* All applications that are to use a different Ruby version and/or gemset can be served separately through Passenger Standalone and hook into the main web server via a reverse proxy configuration (step 6).<br />
<br />
=== Step 5: .rvmrc files and ownerships ===<br />
<br />
This step is crucial for the correct behaviour of the setup. RVM seeks for .rvmrc files when changing folders; if it finds one, it reads it. In these files normally one stores a line like<br />
rvm <ruby_version>@<gemset_name><br />
so the specified environment is set at the entrance of applications' root folder.<br />
<br />
Create /srv/http/refineria/.rvmrc doing<br />
# echo "rvm ree@refinery" > /srv/http/refineria/.rvmrc<br />
, and /srv/http/navegador/.rvmrc with<br />
# echo "rvm 2.0.0@browser" > /srv/http/navegador/.rvmrc<br />
You have to enter to both application root folders now, because every first time that RVM finds a .rvmrc it asks you if you trust the given file, consequently you must validate the two files you have just created.<br />
<br />
These files aid the programs involved to find the correct gems.<br />
<br />
Apart, if applications' files and folders are not owned by the right user you will face database write-access problems. The use of rvmsudo produces ''root''-owned archives when generated by Rails; in the other hand, ''nobody'' is the user for Passenger —if you have not changed it—: who will use and should posses them. Fix this doing<br />
# chown -R nobody.nobody /srv/http/refineria /srv/http/navegador<br />
<br />
=== Step 6: Reverse proxies ===<br />
<br />
You have to start the Passenger Standalone web servers for your applications. So, do<br />
$ cd /srv/http/refineria<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
and<br />
$ cd /srv/http/navegador<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
. The first time that you run a Passenger Standalone it will perform a minor installation.<br />
<br />
Note that you are using ''unix domain'' sockets instead of the commonly-used ''TCP'' sockets; it turns out that unix domain are significantly faster than TCP sockets.<br />
<br />
{{note|If you are experimenting trouble with unix sockets, changing to TCP should work:<br />
rvmsudo passenger start -a 127.0.0.1 -p 3000 -d<br />
}}<br />
<br />
==== Launch Passenger Standalone daemons at system start-up ====<br />
<br />
''Do you have a script? Please post it here.''<br />
<br />
The systemd script below was made for a Typo blog I host at /srv/http/typo. It is located at /etc/systemd/system/passenger_typo.service. I set the Environment= tags (see "man systemd.exec") from the output of "rvm env". The only exception was PATH=, which I had to combine from my regular PATH and the output of rvm env.<br />
<br />
Note: If you do not set the "WorkingDirectory=" variable to your application folder, passenger will fail to find your app and will subsequently shut itself down.<br />
<br />
<pre><br />
[Unit]<br />
Description=Passenger Standalone Script for Typo<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
WorkingDirectory=/srv/http/typo<br />
PIDFile=/srv/http/typo/tmp/pids/passenger.pid<br />
<br />
Environment=PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo/bin:/usr/local/rvm/gems/ruby-2.0.0-p0@global/bin:/usr/local/rvm/rubies/ruby-2.0.0-p0/bin:/usr/local/rvm/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/bin/core_perl<br />
Environment=rvm_env_string=ruby-2.0.0-p0@typo<br />
Environment=rvm_path=/usr/local/rvm<br />
Environment=rvm_ruby_string=ruby-2.0.0-p0<br />
Environment=rvm_gemset_name=typo<br />
Environment=RUBY_VERSION=ruby-2.0.0-p0<br />
Environment=GEM_HOME=/usr/local/rvm/gems/ruby-2.0.0-p0@typo<br />
Environment=GEM_PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo:/usr/local/rvm/gems/ruby-2.0.0-p0@global<br />
Environment=MY_RUBY_HOME=/usr/local/rvm/rubies/ruby-2.0.0-p0<br />
Environment=IRBRC=/usr/local/rvm/rubies/ruby-2.0.0-p0/.irbrc<br />
<br />
ExecStart=/bin/bash -c "rvmsudo passenger start --socket /srv/http/typo/tmp/sockets/passenger.socket -d"<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
</pre><br />
<br />
=== Step 7: Deployment ===<br />
<br />
==== With subdomains ====<br />
<br />
Once again edit /opt/nginx/conf/nginx.conf to include some vital instructions:<br />
<br />
<pre><br />
## RefineryCMS ##<br />
<br />
server {<br />
server_name refinery.domain.com;<br />
root /srv/http/refineria/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/refineria/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
<br />
## BrowserCMS ##<br />
<br />
server {<br />
server_name browser.domain.com;<br />
root /srv/http/navegador/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/navegador/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
{{note|Or if using TCP sockets, configure the ''proxy_pass'' directive like<br />
<pre>proxy_pass http://127.0.0.1:3000;</pre><br />
}}<br />
<br />
==== Without subdomains ====<br />
<br />
If you for some reason do not want to host each application on its own subdomain but rather in a url like: {{ic|site.com/railsapp}} then you could do something like this in your config:<br />
<br />
<pre><br />
server {<br />
server_name site.com;<br />
#Base for the html files etc<br />
root /srv/http/;<br />
<br />
#First application you want hosted under domain site.com/railsapp<br />
location /railsapp {<br />
root /srv/http/railsapp/public;<br />
#you may need to change passenger_base_uri to be the uri you want to point at, ie:<br />
#passenger_base_uri /railsapp;<br />
#but probably only if you are using the other solution with passenger phusion<br />
proxy_pass http://unix:/srv/http/railsapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
<br />
#Second applicatino you want hosted under domain site.com/anotherapp<br />
location /anotherapp {<br />
root /srv/http/anotherapp/public;<br />
#same thing about the passenger_base_uri here, but with value /anotherapp instead<br />
proxy_pass http://unix:/srv/http/anotherapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
At this point you are in conditions to run Nginx with:<br />
<br />
# systemctl start nginx<br />
<br />
and to access both CMSs through ''refinery.domain.com'' and ''browser.domain.com''.<br />
<br />
=== References ===<br />
<br />
* http://beginrescueend.com/integration/passenger<br />
* http://blog.phusion.nl/2010/09/21/phusion-passenger-running-multiple-ruby-versions<br />
* http://www.ruby-journal.com/how-to-setup-rails-app-with-puma-and-nginx/<br />
* https://www.digitalocean.com/community/tutorials/how-to-deploy-a-rails-app-with-puma-and-nginx-on-ubuntu-14-04<br />
<br />
== See also ==<br />
<br />
* [[Ruby]]<br />
* [[Nginx]]<br />
* [[LAMP]]<br />
* [[MySQL]]<br />
<br />
== References ==<br />
<br />
* Ruby on Rails http://rubyonrails.org/download.<br />
* Mongrel http://mongrel.rubyforge.org.</div>Stbinanhttps://wiki.archlinux.org/index.php?title=Ruby_on_Rails&diff=391534Ruby on Rails2015-08-17T15:30:29Z<p>Stbinan: /* Option 2: by systemd */</p>
<hr />
<div>[[Category:Web server]]<br />
[[zh-CN:Ruby on Rails]]<br />
[http://rubyonrails.org/ Ruby on Rails], often shortened to Rails or RoR, is an open source web application framework for the Ruby programming language. It is intended to be used with an Agile development methodology that is used by web developers for rapid development.<br />
<br />
This document describes how to set up the Ruby on Rails Framework on an Arch Linux system.<br />
<br />
== Installation ==<br />
<br />
Ruby on Rails requires [[Ruby]] to be installed, so read that article first for installation instructions. The {{pkg|nodejs}} package is also required.<br />
<br />
Ruby on Rails itself can be installed multiple ways:<br />
<br />
=== Option A: via RubyGems ===<br />
<br />
{{Note|You can also install Rails system-wide using Gems. To do this, run the following commands as root and append them with {{ic|--no-user-install}}. Please read [[Ruby#Installing gems per-user or system-wide]] for possible dangers of using RubyGem in this way.}}<br />
<br />
The following command will install Rails for the current user:<br />
$ gem install rails<br />
<br />
Building the documentation takes a while. If you want to skip it, append {{ic|--no-document}} to the install command.<br />
$ gem install rails --no-document<br />
<br />
gem is a package manager for Ruby modules, somewhat like pacman is to Arch Linux. To update your gems, simply run:<br />
$ gem update<br />
<br />
=== Option B: via pacgem ===<br />
<br />
You can install Rails using {{AUR|pacgem}} from the [[AUR]]. Pacgem automatically creates PKGBUILDs and Arch packages for each of the gems. These packages will then be installed using pacman.<br />
# pacgem rails<br />
<br />
The gem packages can be updated with<br />
# pacgem -u<br />
<br />
=== Option C: from the AUR ===<br />
<br />
{{Warning|This is not recommended, as this might not include the latest Rails version, and additional dependencies may be introduced that may require you to run {{Ic|gem install}} anyway.}}<br />
<br />
There is a {{AUR|ruby-rails}} package available in the [[AUR]].<br />
<br />
=== Option D: from Quarry binary repository ===<br />
<br />
[[pacman|Install]] ''ruby-rails'' from the unofficial [[Unofficial user repositories#quarry|quarry]] repository.<br />
<br />
== Configuration ==<br />
<br />
Rails is bundled with a basic HTTP server called WeBrick. You can create a test application to test it. First, create an application with the rails command:<br />
<br />
$ rails new testapp_name<br />
<br />
{{Note|If you get an error like {{ic|Errno::ENOENT: No such file or directory (...) An error occurred while installing x, and Bundler cannot continue.}}, you might have to configure [[Ruby#Bundler|Bundler]] so that it installs gems per-user and not system-wide. Alternatively, run {{ic|# rails new testapp_name}} once as root. If it has completed successfully, delete {{ic|testapp_name/}} and run {{ic|$ rails new testapp_name}} again as a regular user.}}<br />
{{Note|If you get an error message like this:<br />
{{ic|... FetchError: SSL_connect returned&#61;1 errno&#61; 0 state&#61;SSLv2/v3 read server hello A: sslv3 alert handshake<br />
failure <nowiki>(https://s3.amazonaws.com/ production.s3.rubygems.org/gems/rake-10.0.3.gem)</nowiki> }}<br />
install {{Pkg|nodejs}} and try again.}}<br />
<br />
This creates a new folder inside your current working directory. <br />
<br />
$ cd testapp_name<br />
<br />
Next start the web server. It listens on port 3000 by default:<br />
<br />
$ rails server<br />
<br />
Now visit the testapp_name website on your local machine by opening <nowiki>http://localhost:3000</nowiki> in your browser<br />
{{Note|If Ruby complains about not being able to find a JavaScript runtime, install {{Pkg|nodejs}}.}}<br />
<br />
A test-page should shown greeting you "Welcome aboard".<br />
<br />
== Application servers ==<br />
<br />
The built-in Ruby On Rails HTTP server (WeBrick) is convenient for basic development, but it is not recommended for production use. Instead, you should use an application server such as [[#Thin]], [[#Unicorn]] or [[#Apache/Nginx (using Phusion Passenger)|Phusion Passenger]].<br />
<br />
=== Thin ===<br />
<br />
[http://code.macournoyer.com/thin/ Thin] is a fast and very simple Ruby web server.<br />
<br />
First install thin gem:<br />
$ gem install thin<br />
<br />
Then start it using:<br />
$ thin start<br />
<br />
=== Unicorn ===<br />
<br />
Unicorn is an application server that cannot talk directly to clients. Instead, a web server must sit between clients and Unicorn, proxying requests as needed. [http://unicorn.bogomips.org/ Unicorn] is loosely based on Mongrel. It is used by Github, and it uses an architecture that tries hard to find the best child for handling a request. [https://github.com/blog/517-unicorn Explanation of differences between Unicorn and Mongrel].<br />
<br />
Install the Unicorn gem:<br />
# gem install unicorn<br />
<br />
Then create a configuration file for your application in {{ic|/etc/unicorn/}}. For example; here is a configuration example (Based on [http://www.warden.pl/2011/01/07/running-redmine-under-unicorn-in-debian/]) for Redmine:<br />
<br />
{{hc|/etc/unicorn/redmine.ru|<nowiki><br />
working_directory "/srv/http/redmine"<br />
pid "/tmp/redmine.pid"<br />
<br />
preload_app true<br />
timeout 60<br />
worker_processes 4<br />
listen 4000<br />
stderr_path('/var/log/unicorn.log')<br />
<br />
GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true<br />
<br />
after_fork do |server, worker|<br />
#start the worker on port 4000, 4001, 4002 etc...<br />
addr = "0.0.0.0:#{4000 + worker.nr}"<br />
# infinite tries to start the worker<br />
server.listen(addr, :tries => -1, :delay => -1, :backlog => 128)<br />
<br />
#Drop privileges if running as root<br />
worker.user('nobody', 'nobody') if Process.euid == 0<br />
end<br />
</nowiki>}}<br />
<br />
Start it using:<br />
# /usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
==== Systemd service ====<br />
<br />
Put the following contents in {{ic|/etc/systemd/system/unicorn.service}}:<br />
{{hc|/etc/systemd/system/unicorn.service|2=<br />
[Unit]<br />
Description=Unicorn application server<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
User=redmine<br />
ExecStart=/usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
}}<br />
<br />
You can now easily start and stop unicorn using systemctl<br />
<br />
==== Nginx Configuration ====<br />
<br />
After setting up [[Nginx]], configure unicorn as an upstream server using something like this (Warning: this is a stripped example. It probably does not work without additional configuration):<br />
{{bc|1=<br />
http {<br />
upstream unicorn {<br />
server 127.0.0.1:4000 fail_timeout=0;<br />
server 127.0.0.1:4001 fail_timeout=0;<br />
server 127.0.0.1:4002 fail_timeout=0;<br />
server 127.0.0.1:4003 fail_timeout=0;<br />
}<br />
<br />
server {<br />
listen 80 default;<br />
server_name YOURHOSTNAMEHERE;<br />
<br />
location / {<br />
root /srv/http/redmine/public;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
proxy_pass http://unicorn;<br />
}<br />
}<br />
}<br />
}}<br />
<br />
=== Apache/Nginx (using Phusion Passenger) ===<br />
<br />
[http://www.modrails.com/ Passenger] also known as {{ic|mod_rails}} is a module available for [[Nginx]] and [[Apache]], that greatly simplifies setting up a Rails server environment. Nginx does not support modules as Apache and has to be compiled with {{ic|mod_rails}} in order to support Passenger; let Passenger compile it for you. As for Apache, let Passenger set up the module for you.<br />
<br />
Start by installing the 'passenger' gem:<br />
# gem install passenger<br />
<br />
If you are aiming to use [[Apache]], run:<br />
# passenger-install-apache2-module<br />
<br />
In case a rails application is deployed with a sub-URI, like http://example.com/yourapplication, some additional configuration is required, see [http://www.modrails.com/documentation/Users%20guide%20Apache.html#deploying_rails_to_sub_uri the modrails documentation]<br />
<br />
For [[Nginx]]:<br />
# passenger-install-nginx-module<br />
<br />
The installer will provide you with any additional information regarding the installation (such as installing additional libraries).<br />
<br />
To serve an application with Nginx, configure it as follows:<br />
<pre><br />
server {<br />
server_name app.example.org;<br />
root path_to_app/public; # Be sure to point to 'public' folder!<br />
passenger_enabled on;<br />
rails_env development; # Rails environment.<br />
}<br />
</pre><br />
<br />
=== Puma (with Nginx as reverse proxy server) ===<br />
<br />
[http://puma.io/ Puma] ([https://github.com/puma/puma Github Page]) is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications, and is considered the replacement for Webrick and Mongrel. It was designed to be the go-to server for Rubinius, but also works well with JRuby and MRI. While reverse proxy server would acts as a load balancer that routes all external requests to a pool of web apps.<br />
<br />
For a webserver it is better to use a server user and group, check [[Users_and_groups#Example_adding_a_user]], below use {{ic|rails}} as user name and {{ic|server}} as group name, also {{ic|my_app}} as rails app name.<br />
<br />
Start by copying your app to /var/www/my_app. And set new ownership with<br />
# cd /var/www/<br />
# chown -R rails:server my_app<br />
<br />
and permission for user with<br />
# chmod -R 775 my_app<br />
<br />
Then add puma gem in the Gemfile and install with<br />
$ cd my_app <br />
$ bundle install<br />
<br />
Also install {{ic|nginx}} by pacman.<br />
<br />
Under your app folder, create sockets, pid and log folder with<br />
$ mkdir -p shared/pids shared/sockets shared/log<br />
<br />
Backup nginx.conf with<br />
# cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup<br />
<br />
Then create a new nginx.conf file with your favorite editor, copy codes below and modify as you like:<br />
<pre><br />
#user html;<br />
worker_processes 1; # this may connect with the worker numbers puma can use.<br />
<br />
#error_log logs/error.log;<br />
#error_log logs/error.log notice;<br />
#error_log logs/error.log info;<br />
<br />
#pid logs/nginx.pid;<br />
<br />
<br />
events {<br />
worker_connections 1024;<br />
}<br />
<br />
http {<br />
upstream app {<br />
# Path to Puma SOCK file, as defined previously<br />
server unix:/var/www/my_app/shared/sockets/puma.sock;<br />
}<br />
<br />
server {<br />
listen 80;<br />
server_name localhost; # or your server name<br />
<br />
root /var/www/my_app/public;<br />
<br />
try_files $uri/index.html $uri @app;<br />
<br />
location @app {<br />
proxy_pass http://app;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
}<br />
<br />
error_page 500 502 503 504 /500.html;<br />
client_max_body_size 4G;<br />
keepalive_timeout 10;<br />
}<br />
}</pre><br />
<br />
Start nginx service with<br />
# systemctl start nginx<br />
<br />
<br />
There are several ways to start puma server, two ways are recommended below:<br />
<br />
==== Option A: With config file ====<br />
<br />
Create file {{ic|config/puma.rb}}, copy codes below and modify as you like:<br />
<pre><br />
# Change to match your CPU core count<br />
# You can check available worker numbers with $ grep -c processor /proc/cpuinfo<br />
# also see the comment in the nginx.conf<br />
workers 2<br />
<br />
# Min and Max threads per worker<br />
#threads 1, 6<br />
<br />
app_dir = File.expand_path("../..", __FILE__)<br />
shared_dir = "#{app_dir}/shared"<br />
<br />
# Default to production<br />
#rails_env = ENV['RAILS_ENV'] || "production"<br />
#environment rails_env<br />
<br />
# Set up socket location<br />
bind "unix://#{shared_dir}/sockets/puma.sock"<br />
<br />
# Logging<br />
#stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true<br />
<br />
# Set master PID and state locations<br />
pidfile "#{shared_dir}/pids/puma.pid"<br />
#state_path "#{shared_dir}/pids/puma.state"<br />
#activate_control_app<br />
<br />
#on_worker_boot do<br />
# require "active_record"<br />
# ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished<br />
# ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])<br />
#end</pre><br />
<br />
and start server with<br />
$ bundle exec puma -C config/puma.rb<br />
<br />
You can also run it in background with parameter {{ic|-d}} and check with<br />
$ ps aux| grep puma<br />
when you want to {{ic|kill}} it.<br />
<br />
==== Option 2: by systemd ====<br />
<br />
Create a new systemd unit {{ic|puma.service}} under ~/.config/systemd/user/ and copy codes below<br />
<pre><br />
[Unit]<br />
Description=Puma application server<br />
After=network.target<br />
<br />
[Service]<br />
WorkingDirectory=/var/www/my_app<br />
#Environment=RAILS_ENV=production<br />
#User=rails<br />
PIDFile=/var/www/my_app/shared/pids/puma.pid<br />
ExecStart=/home/rails/.gem/ruby/2.2.0/bin/bundle exec \<br />
/home/rails/.gem/ruby/2.2.0/bin/puma \<br />
-b unix:///var/www/my_app/shared/sockets/puma.sock \<br />
--pidfile /var/www/my_app/shared/pids/puma.pid<br />
<br />
[Install]<br />
WantedBy=multi-user.target</pre><br />
<br />
Then start puma with<br />
$ systemctl --user start puma<br />
<br />
For further reading take a look at [[Ruby_on_Rails#References]]<br />
<br />
== Databases ==<br />
<br />
Most web applications will need to interact with some sort of database. ActiveRecord (the ORM used by Rails to provide database abstraction) supports several database vendors, the most popular of which are MySQL, SQLite, and PostgreSQL.<br />
<br />
=== SQLite ===<br />
<br />
SQLite is the default lightweight database for Ruby on Rails. To enable SQLite, simply install {{Pkg|sqlite}}.<br />
<br />
=== PostgreSQL ===<br />
<br />
Install {{Pkg|postgresql}}.<br />
<br />
=== MySQL ===<br />
<br />
First, install and configure a MySQL server. Please refer to [[MySQL]] on how to do this.<br />
<br />
A gem with some native extensions is required, probably best installed as root:<br />
# gem install mysql<br />
<br />
You can generate a rails application configured for MySQL by using the {{ic|-d}} parameter:<br />
$ rails new testapp_name -d mysql<br />
<br />
You then need to edit {{ic|config/database.yml}}. Rails uses different databases for development, testing, production and other environments. Here is an example development configuration for MySQL running on localhost:<br />
<br />
development:<br />
adapter: mysql<br />
database: my_application_database<br />
username: development<br />
password: my_secret_password<br />
<br />
Note that you do not have to actually create the database using MySQL, as this can be done via Rails with:<br />
# rake db:create<br />
<br />
If no errors are shown, then your database has been created and Rails can talk to your MySQL database.<br />
<br />
== The Perfect Rails Setup ==<br />
<br />
''Phusion Passenger running multiple Ruby versions.''<br />
<br />
* [https://www.archlinux.org/ Arch Linux]: A simple, lightweight distribution. ;)<br />
* [http://www.nginx.org/ Nginx]: A fast and lightweight '''web server''' with a strong focus on high concurrency, performance and low memory usage.<br />
* [http://www.modrails.com/ Passenger] (a.k.a. mod_rails or mod_rack): Supports both Apache and Nginx web servers. It makes deployment of Ruby web applications, such as those built on Ruby on Rails web framework, a breeze.<br />
* [https://rvm.io/ Ruby Version Manager] (RVM): A command-line tool which allows you to easily install, manage, and work with multiple Ruby environments from interpreters to sets of gems. RVM lets you deploy each project with its own completely self-contained and dedicated environment —from the specific version of ruby, all the way down to the precise set of required gems to run your application—.<br />
* [http://sqlite.org/ SQLite]: The default lightweight '''database''' for Ruby on Rails.<br />
<br />
=== Step 0: SQLite ===<br />
<br />
Install {{Pkg|sqlite}}.<br />
<br />
{{note|Of course SQLite is not critical in this setup, you can use MySQL and PostgreSQL as well.}}<br />
<br />
=== Step 1: RVM ===<br />
<br />
Make a multi-user [[RVM]] installation as specified [[RVM#Multi-user_installation|here]].<br />
<br />
In the 'adding users to the rvm group' step, do<br />
# usermod -a -G rvm http<br />
# usermod -a -G rvm nobody<br />
<br />
{{ic|http}} and {{ic|nobody}} are the users related to Nginx and Passenger, respectively.<br />
<br />
{{note|Maybe adding the 'nobody' user to the 'rvm' group is not necessary.}}<br />
<br />
=== Step 2: Rubies ===<br />
<br />
Once you have a working RVM installation in your hands, it is time to install the latest Ruby interpreter<br />
{{Note|During the installation of Ruby patches will be applied. Consider installing the {{ic|base-devel}} group beforehand.}}<br />
<br />
$ rvm install 2.0.0<br />
<br />
{{Note| It may be useful to delete the 'global' gemsets of the environments that have web applications. Their gems might somehow interfere with Passenger. In that case, a {{ic|rvm 2.0.0 do gemset delete global}} is sufficient.}}<br />
<br />
=== Step 3: Nginx with Passenger support ===<br />
<br />
Run the following to allow passenger install nginx:<br />
$ rvm use 2.0.0 <br />
$ gem install passenger<br />
$ rvmsudo passenger-install-nginx-module<br />
<br />
The passenger gem will be put into the ''default'' gemset.<br />
<br />
This will download the sources of Nginx, compile and install it for you. It will guide you through all the process. Note that the default location for Nginx will be {{ic|/opt/nginx}}.<br />
<br />
{{Note|If you encounter a compilation error regarding Boost threads, see [https://bbs.archlinux.org/viewtopic.php?id&#61;139164 this] article.}}<br />
<br />
After completion, add the following two lines into the 'http block' at {{ic|/opt/nginx/conf/nginx.conf}} that look like:<br />
<br />
http { <br />
...<br />
passenger_root /usr/local/rvm/gems/ruby-2.0.0-p353/gems/passenger-3.0.9;<br />
passenger_ruby /usr/local/rvm/wrappers/ruby-2.0.0-p353/ruby;<br />
...<br />
}<br />
<br />
{{Note|This step is currently being done automatically by the installer script.}}<br />
<br />
=== Step 4: Gemsets and Apps ===<br />
<br />
For each Rails application you should have a gemset. Suppose that you want to try [http://refinerycms.com RefineryCMS] against [http://www.browsercms.org BrowserCMS], two open-source Content Management Systems based on Rails.<br />
<br />
Install RefineryCMS first:<br />
<br />
$ rvm use 2.0.0@refinery --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install refinerycms refinerycms-i18n sqlite3<br />
<br />
Deploy a RefineryCMS instance called ''refineria'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo refinerycms refineria<br />
<br />
Install BrowserCMS in a different gemset:<br />
<br />
$ rvm use 2.0.0@browser --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install browsercms sqlite3<br />
<br />
Deploy a BrowserCMS instance called ''navegador'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo browsercms demo navegador<br />
$ cd /srv/http/navegador<br />
$ rvmsudo rake db:install<br />
<br />
=== Passenger for Nginx and Passenger Standalone ===<br />
<br />
Observe that the passenger gem was installed three times and with different intentions; in the environments<br />
* ''2.0.0'' => for Nginx,<br />
* ''2.0.0@refinery'' => Standalone<br />
* ''2.0.0@browser'' => Standalone<br />
<br />
The strategy is to combine Passenger for Nginx with Passenger Standalone. One must first identify the Ruby environment (interpreter plus gemset) that one uses the most; in this setup the Ruby interpreter and the default gemset were selected. One then proceeds with setting up Passenger for Nginx to use that environment (step 3).<br />
* Applications within the chosen environment can be served as in [[#Apache.2FNginx .28using Phusion Passenger.29|Apache/Nginx (using Phusion Passenger)]], page up in this article.<br />
* All applications that are to use a different Ruby version and/or gemset can be served separately through Passenger Standalone and hook into the main web server via a reverse proxy configuration (step 6).<br />
<br />
=== Step 5: .rvmrc files and ownerships ===<br />
<br />
This step is crucial for the correct behaviour of the setup. RVM seeks for .rvmrc files when changing folders; if it finds one, it reads it. In these files normally one stores a line like<br />
rvm <ruby_version>@<gemset_name><br />
so the specified environment is set at the entrance of applications' root folder.<br />
<br />
Create /srv/http/refineria/.rvmrc doing<br />
# echo "rvm ree@refinery" > /srv/http/refineria/.rvmrc<br />
, and /srv/http/navegador/.rvmrc with<br />
# echo "rvm 2.0.0@browser" > /srv/http/navegador/.rvmrc<br />
You have to enter to both application root folders now, because every first time that RVM finds a .rvmrc it asks you if you trust the given file, consequently you must validate the two files you have just created.<br />
<br />
These files aid the programs involved to find the correct gems.<br />
<br />
Apart, if applications' files and folders are not owned by the right user you will face database write-access problems. The use of rvmsudo produces ''root''-owned archives when generated by Rails; in the other hand, ''nobody'' is the user for Passenger —if you have not changed it—: who will use and should posses them. Fix this doing<br />
# chown -R nobody.nobody /srv/http/refineria /srv/http/navegador<br />
<br />
=== Step 6: Reverse proxies ===<br />
<br />
You have to start the Passenger Standalone web servers for your applications. So, do<br />
$ cd /srv/http/refineria<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
and<br />
$ cd /srv/http/navegador<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
. The first time that you run a Passenger Standalone it will perform a minor installation.<br />
<br />
Note that you are using ''unix domain'' sockets instead of the commonly-used ''TCP'' sockets; it turns out that unix domain are significantly faster than TCP sockets.<br />
<br />
{{note|If you are experimenting trouble with unix sockets, changing to TCP should work:<br />
rvmsudo passenger start -a 127.0.0.1 -p 3000 -d<br />
}}<br />
<br />
==== Launch Passenger Standalone daemons at system start-up ====<br />
<br />
''Do you have a script? Please post it here.''<br />
<br />
The systemd script below was made for a Typo blog I host at /srv/http/typo. It is located at /etc/systemd/system/passenger_typo.service. I set the Environment= tags (see "man systemd.exec") from the output of "rvm env". The only exception was PATH=, which I had to combine from my regular PATH and the output of rvm env.<br />
<br />
Note: If you do not set the "WorkingDirectory=" variable to your application folder, passenger will fail to find your app and will subsequently shut itself down.<br />
<br />
<pre><br />
[Unit]<br />
Description=Passenger Standalone Script for Typo<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
WorkingDirectory=/srv/http/typo<br />
PIDFile=/srv/http/typo/tmp/pids/passenger.pid<br />
<br />
Environment=PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo/bin:/usr/local/rvm/gems/ruby-2.0.0-p0@global/bin:/usr/local/rvm/rubies/ruby-2.0.0-p0/bin:/usr/local/rvm/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/bin/core_perl<br />
Environment=rvm_env_string=ruby-2.0.0-p0@typo<br />
Environment=rvm_path=/usr/local/rvm<br />
Environment=rvm_ruby_string=ruby-2.0.0-p0<br />
Environment=rvm_gemset_name=typo<br />
Environment=RUBY_VERSION=ruby-2.0.0-p0<br />
Environment=GEM_HOME=/usr/local/rvm/gems/ruby-2.0.0-p0@typo<br />
Environment=GEM_PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo:/usr/local/rvm/gems/ruby-2.0.0-p0@global<br />
Environment=MY_RUBY_HOME=/usr/local/rvm/rubies/ruby-2.0.0-p0<br />
Environment=IRBRC=/usr/local/rvm/rubies/ruby-2.0.0-p0/.irbrc<br />
<br />
ExecStart=/bin/bash -c "rvmsudo passenger start --socket /srv/http/typo/tmp/sockets/passenger.socket -d"<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
</pre><br />
<br />
=== Step 7: Deployment ===<br />
<br />
==== With subdomains ====<br />
<br />
Once again edit /opt/nginx/conf/nginx.conf to include some vital instructions:<br />
<br />
<pre><br />
## RefineryCMS ##<br />
<br />
server {<br />
server_name refinery.domain.com;<br />
root /srv/http/refineria/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/refineria/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
<br />
## BrowserCMS ##<br />
<br />
server {<br />
server_name browser.domain.com;<br />
root /srv/http/navegador/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/navegador/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
{{note|Or if using TCP sockets, configure the ''proxy_pass'' directive like<br />
<pre>proxy_pass http://127.0.0.1:3000;</pre><br />
}}<br />
<br />
==== Without subdomains ====<br />
<br />
If you for some reason do not want to host each application on its own subdomain but rather in a url like: {{ic|site.com/railsapp}} then you could do something like this in your config:<br />
<br />
<pre><br />
server {<br />
server_name site.com;<br />
#Base for the html files etc<br />
root /srv/http/;<br />
<br />
#First application you want hosted under domain site.com/railsapp<br />
location /railsapp {<br />
root /srv/http/railsapp/public;<br />
#you may need to change passenger_base_uri to be the uri you want to point at, ie:<br />
#passenger_base_uri /railsapp;<br />
#but probably only if you are using the other solution with passenger phusion<br />
proxy_pass http://unix:/srv/http/railsapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
<br />
#Second applicatino you want hosted under domain site.com/anotherapp<br />
location /anotherapp {<br />
root /srv/http/anotherapp/public;<br />
#same thing about the passenger_base_uri here, but with value /anotherapp instead<br />
proxy_pass http://unix:/srv/http/anotherapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
At this point you are in conditions to run Nginx with:<br />
<br />
# systemctl start nginx<br />
<br />
and to access both CMSs through ''refinery.domain.com'' and ''browser.domain.com''.<br />
<br />
=== References ===<br />
<br />
* http://beginrescueend.com/integration/passenger<br />
* http://blog.phusion.nl/2010/09/21/phusion-passenger-running-multiple-ruby-versions<br />
* http://www.ruby-journal.com/how-to-setup-rails-app-with-puma-and-nginx/<br />
* https://www.digitalocean.com/community/tutorials/how-to-deploy-a-rails-app-with-puma-and-nginx-on-ubuntu-14-04<br />
<br />
== See also ==<br />
<br />
* [[Ruby]]<br />
* [[Nginx]]<br />
* [[LAMP]]<br />
* [[MySQL]]<br />
<br />
== References ==<br />
<br />
* Ruby on Rails http://rubyonrails.org/download.<br />
* Mongrel http://mongrel.rubyforge.org.</div>Stbinanhttps://wiki.archlinux.org/index.php?title=Ruby_on_Rails&diff=391498Ruby on Rails2015-08-17T09:45:32Z<p>Stbinan: /* Option 2: by systemd */</p>
<hr />
<div>[[Category:Web server]]<br />
[[zh-CN:Ruby on Rails]]<br />
[http://rubyonrails.org/ Ruby on Rails], often shortened to Rails or RoR, is an open source web application framework for the Ruby programming language. It is intended to be used with an Agile development methodology that is used by web developers for rapid development.<br />
<br />
This document describes how to set up the Ruby on Rails Framework on an Arch Linux system.<br />
<br />
== Installation ==<br />
<br />
Ruby on Rails requires [[Ruby]] to be installed, so read that article first for installation instructions. The {{pkg|nodejs}} package is also required.<br />
<br />
Ruby on Rails itself can be installed multiple ways:<br />
<br />
=== Option A: via RubyGems ===<br />
<br />
{{Note|You can also install Rails system-wide using Gems. To do this, run the following commands as root and append them with {{ic|--no-user-install}}. Please read [[Ruby#Installing gems per-user or system-wide]] for possible dangers of using RubyGem in this way.}}<br />
<br />
The following command will install Rails for the current user:<br />
$ gem install rails<br />
<br />
Building the documentation takes a while. If you want to skip it, append {{ic|--no-document}} to the install command.<br />
$ gem install rails --no-document<br />
<br />
gem is a package manager for Ruby modules, somewhat like pacman is to Arch Linux. To update your gems, simply run:<br />
$ gem update<br />
<br />
=== Option B: via pacgem ===<br />
<br />
You can install Rails using {{AUR|pacgem}} from the [[AUR]]. Pacgem automatically creates PKGBUILDs and Arch packages for each of the gems. These packages will then be installed using pacman.<br />
# pacgem rails<br />
<br />
The gem packages can be updated with<br />
# pacgem -u<br />
<br />
=== Option C: from the AUR ===<br />
<br />
{{Warning|This is not recommended, as this might not include the latest Rails version, and additional dependencies may be introduced that may require you to run {{Ic|gem install}} anyway.}}<br />
<br />
There is a {{AUR|ruby-rails}} package available in the [[AUR]].<br />
<br />
=== Option D: from Quarry binary repository ===<br />
<br />
[[pacman|Install]] ''ruby-rails'' from the unofficial [[Unofficial user repositories#quarry|quarry]] repository.<br />
<br />
== Configuration ==<br />
<br />
Rails is bundled with a basic HTTP server called WeBrick. You can create a test application to test it. First, create an application with the rails command:<br />
<br />
$ rails new testapp_name<br />
<br />
{{Note|If you get an error like {{ic|Errno::ENOENT: No such file or directory (...) An error occurred while installing x, and Bundler cannot continue.}}, you might have to configure [[Ruby#Bundler|Bundler]] so that it installs gems per-user and not system-wide. Alternatively, run {{ic|# rails new testapp_name}} once as root. If it has completed successfully, delete {{ic|testapp_name/}} and run {{ic|$ rails new testapp_name}} again as a regular user.}}<br />
{{Note|If you get an error message like this:<br />
{{ic|... FetchError: SSL_connect returned&#61;1 errno&#61; 0 state&#61;SSLv2/v3 read server hello A: sslv3 alert handshake<br />
failure <nowiki>(https://s3.amazonaws.com/ production.s3.rubygems.org/gems/rake-10.0.3.gem)</nowiki> }}<br />
install {{Pkg|nodejs}} and try again.}}<br />
<br />
This creates a new folder inside your current working directory. <br />
<br />
$ cd testapp_name<br />
<br />
Next start the web server. It listens on port 3000 by default:<br />
<br />
$ rails server<br />
<br />
Now visit the testapp_name website on your local machine by opening <nowiki>http://localhost:3000</nowiki> in your browser<br />
{{Note|If Ruby complains about not being able to find a JavaScript runtime, install {{Pkg|nodejs}}.}}<br />
<br />
A test-page should shown greeting you "Welcome aboard".<br />
<br />
== Application servers ==<br />
<br />
The built-in Ruby On Rails HTTP server (WeBrick) is convenient for basic development, but it is not recommended for production use. Instead, you should use an application server such as [[#Thin]], [[#Unicorn]] or [[#Apache/Nginx (using Phusion Passenger)|Phusion Passenger]].<br />
<br />
=== Thin ===<br />
<br />
[http://code.macournoyer.com/thin/ Thin] is a fast and very simple Ruby web server.<br />
<br />
First install thin gem:<br />
$ gem install thin<br />
<br />
Then start it using:<br />
$ thin start<br />
<br />
=== Unicorn ===<br />
<br />
Unicorn is an application server that cannot talk directly to clients. Instead, a web server must sit between clients and Unicorn, proxying requests as needed. [http://unicorn.bogomips.org/ Unicorn] is loosely based on Mongrel. It is used by Github, and it uses an architecture that tries hard to find the best child for handling a request. [https://github.com/blog/517-unicorn Explanation of differences between Unicorn and Mongrel].<br />
<br />
Install the Unicorn gem:<br />
# gem install unicorn<br />
<br />
Then create a configuration file for your application in {{ic|/etc/unicorn/}}. For example; here is a configuration example (Based on [http://www.warden.pl/2011/01/07/running-redmine-under-unicorn-in-debian/]) for Redmine:<br />
<br />
{{hc|/etc/unicorn/redmine.ru|<nowiki><br />
working_directory "/srv/http/redmine"<br />
pid "/tmp/redmine.pid"<br />
<br />
preload_app true<br />
timeout 60<br />
worker_processes 4<br />
listen 4000<br />
stderr_path('/var/log/unicorn.log')<br />
<br />
GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true<br />
<br />
after_fork do |server, worker|<br />
#start the worker on port 4000, 4001, 4002 etc...<br />
addr = "0.0.0.0:#{4000 + worker.nr}"<br />
# infinite tries to start the worker<br />
server.listen(addr, :tries => -1, :delay => -1, :backlog => 128)<br />
<br />
#Drop privileges if running as root<br />
worker.user('nobody', 'nobody') if Process.euid == 0<br />
end<br />
</nowiki>}}<br />
<br />
Start it using:<br />
# /usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
==== Systemd service ====<br />
<br />
Put the following contents in {{ic|/etc/systemd/system/unicorn.service}}:<br />
{{hc|/etc/systemd/system/unicorn.service|2=<br />
[Unit]<br />
Description=Unicorn application server<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
User=redmine<br />
ExecStart=/usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
}}<br />
<br />
You can now easily start and stop unicorn using systemctl<br />
<br />
==== Nginx Configuration ====<br />
<br />
After setting up [[Nginx]], configure unicorn as an upstream server using something like this (Warning: this is a stripped example. It probably does not work without additional configuration):<br />
{{bc|1=<br />
http {<br />
upstream unicorn {<br />
server 127.0.0.1:4000 fail_timeout=0;<br />
server 127.0.0.1:4001 fail_timeout=0;<br />
server 127.0.0.1:4002 fail_timeout=0;<br />
server 127.0.0.1:4003 fail_timeout=0;<br />
}<br />
<br />
server {<br />
listen 80 default;<br />
server_name YOURHOSTNAMEHERE;<br />
<br />
location / {<br />
root /srv/http/redmine/public;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
proxy_pass http://unicorn;<br />
}<br />
}<br />
}<br />
}}<br />
<br />
=== Apache/Nginx (using Phusion Passenger) ===<br />
<br />
[http://www.modrails.com/ Passenger] also known as {{ic|mod_rails}} is a module available for [[Nginx]] and [[Apache]], that greatly simplifies setting up a Rails server environment. Nginx does not support modules as Apache and has to be compiled with {{ic|mod_rails}} in order to support Passenger; let Passenger compile it for you. As for Apache, let Passenger set up the module for you.<br />
<br />
Start by installing the 'passenger' gem:<br />
# gem install passenger<br />
<br />
If you are aiming to use [[Apache]], run:<br />
# passenger-install-apache2-module<br />
<br />
In case a rails application is deployed with a sub-URI, like http://example.com/yourapplication, some additional configuration is required, see [http://www.modrails.com/documentation/Users%20guide%20Apache.html#deploying_rails_to_sub_uri the modrails documentation]<br />
<br />
For [[Nginx]]:<br />
# passenger-install-nginx-module<br />
<br />
The installer will provide you with any additional information regarding the installation (such as installing additional libraries).<br />
<br />
To serve an application with Nginx, configure it as follows:<br />
<pre><br />
server {<br />
server_name app.example.org;<br />
root path_to_app/public; # Be sure to point to 'public' folder!<br />
passenger_enabled on;<br />
rails_env development; # Rails environment.<br />
}<br />
</pre><br />
<br />
=== Puma (with Nginx as reverse proxy server) ===<br />
<br />
[http://puma.io/ Puma] ([https://github.com/puma/puma Github Page]) is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications, and is considered the replacement for Webrick and Mongrel. It was designed to be the go-to server for Rubinius, but also works well with JRuby and MRI. While reverse proxy server would acts as a load balancer that routes all external requests to a pool of web apps.<br />
<br />
For a webserver it is better to use a server user and group, check [[Users_and_groups#Example_adding_a_user]], below use {{ic|rails}} as user name and {{ic|server}} as group name, also {{ic|my_app}} as rails app name.<br />
<br />
Start by copying your app to /var/www/my_app. And set new ownership with<br />
# cd /var/www/<br />
# chown -R rails:server my_app<br />
<br />
and permission for user with<br />
# chmod -R 775 my_app<br />
<br />
Then add puma gem in the Gemfile and install with<br />
$ cd my_app <br />
$ bundle install<br />
<br />
Also install {{ic|nginx}} by pacman.<br />
<br />
Under your app folder, create sockets, pid and log folder with<br />
$ mkdir -p shared/pids shared/sockets shared/log<br />
<br />
Backup nginx.conf with<br />
# cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup<br />
<br />
Then create a new nginx.conf file with your favorite editor, copy codes below and modify as you like:<br />
<pre><br />
#user html;<br />
worker_processes 1; # this may connect with the worker numbers puma can use.<br />
<br />
#error_log logs/error.log;<br />
#error_log logs/error.log notice;<br />
#error_log logs/error.log info;<br />
<br />
#pid logs/nginx.pid;<br />
<br />
<br />
events {<br />
worker_connections 1024;<br />
}<br />
<br />
http {<br />
upstream app {<br />
# Path to Puma SOCK file, as defined previously<br />
server unix:/var/www/my_app/shared/sockets/puma.sock;<br />
}<br />
<br />
server {<br />
listen 80;<br />
server_name localhost; # or your server name<br />
<br />
root /var/www/my_app/public;<br />
<br />
try_files $uri/index.html $uri @app;<br />
<br />
location @app {<br />
proxy_pass http://app;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
}<br />
<br />
error_page 500 502 503 504 /500.html;<br />
client_max_body_size 4G;<br />
keepalive_timeout 10;<br />
}<br />
}</pre><br />
<br />
Start nginx service with<br />
# systemctl start nginx<br />
<br />
<br />
There are several ways to start puma server, two ways are recommended below:<br />
<br />
==== Option A: With config file ====<br />
<br />
Create file {{ic|config/puma.rb}}, copy codes below and modify as you like:<br />
<pre><br />
# Change to match your CPU core count<br />
# You can check available worker numbers with $ grep -c processor /proc/cpuinfo<br />
# also see the comment in the nginx.conf<br />
workers 2<br />
<br />
# Min and Max threads per worker<br />
#threads 1, 6<br />
<br />
app_dir = File.expand_path("../..", __FILE__)<br />
shared_dir = "#{app_dir}/shared"<br />
<br />
# Default to production<br />
#rails_env = ENV['RAILS_ENV'] || "production"<br />
#environment rails_env<br />
<br />
# Set up socket location<br />
bind "unix://#{shared_dir}/sockets/puma.sock"<br />
<br />
# Logging<br />
#stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true<br />
<br />
# Set master PID and state locations<br />
pidfile "#{shared_dir}/pids/puma.pid"<br />
#state_path "#{shared_dir}/pids/puma.state"<br />
#activate_control_app<br />
<br />
#on_worker_boot do<br />
# require "active_record"<br />
# ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished<br />
# ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])<br />
#end</pre><br />
<br />
and start server with<br />
$ bundle exec puma -C config/puma.rb<br />
<br />
You can also run it in background with parameter {{ic|-d}} and check with<br />
$ ps aux| grep puma<br />
when you want to {{ic|kill}} it.<br />
<br />
==== Option 2: by systemd ====<br />
<br />
Create a new systemd unit {{ic|puma.service}} under /usr/lib/systemd/system/ and copy codes below<br />
<pre><br />
[Unit]<br />
Description=Puma application server<br />
After=network.target<br />
<br />
[Service]<br />
WorkingDirectory=/var/www/my_app<br />
#Environment=RAILS_ENV=production<br />
User=rails<br />
PIDFile=/var/www/my_app/shared/pids/puma.pid<br />
ExecStart=/home/rails/.gem/ruby/2.2.0/bin/bundle exec \<br />
/home/rails/.gem/ruby/2.2.0/bin/puma \<br />
-b unix:///var/www/my_app/shared/sockets/puma.sock \<br />
--pidfile /var/www/my_app/shared/pids/puma.pid<br />
<br />
[Install]<br />
WantedBy=multi-user.target</pre><br />
<br />
Then start puma with<br />
# systemctl start puma<br />
<br />
For further reading take a look at [[Ruby_on_Rails#References]]<br />
<br />
== Databases ==<br />
<br />
Most web applications will need to interact with some sort of database. ActiveRecord (the ORM used by Rails to provide database abstraction) supports several database vendors, the most popular of which are MySQL, SQLite, and PostgreSQL.<br />
<br />
=== SQLite ===<br />
<br />
SQLite is the default lightweight database for Ruby on Rails. To enable SQLite, simply install {{Pkg|sqlite}}.<br />
<br />
=== PostgreSQL ===<br />
<br />
Install {{Pkg|postgresql}}.<br />
<br />
=== MySQL ===<br />
<br />
First, install and configure a MySQL server. Please refer to [[MySQL]] on how to do this.<br />
<br />
A gem with some native extensions is required, probably best installed as root:<br />
# gem install mysql<br />
<br />
You can generate a rails application configured for MySQL by using the {{ic|-d}} parameter:<br />
$ rails new testapp_name -d mysql<br />
<br />
You then need to edit {{ic|config/database.yml}}. Rails uses different databases for development, testing, production and other environments. Here is an example development configuration for MySQL running on localhost:<br />
<br />
development:<br />
adapter: mysql<br />
database: my_application_database<br />
username: development<br />
password: my_secret_password<br />
<br />
Note that you do not have to actually create the database using MySQL, as this can be done via Rails with:<br />
# rake db:create<br />
<br />
If no errors are shown, then your database has been created and Rails can talk to your MySQL database.<br />
<br />
== The Perfect Rails Setup ==<br />
<br />
''Phusion Passenger running multiple Ruby versions.''<br />
<br />
* [https://www.archlinux.org/ Arch Linux]: A simple, lightweight distribution. ;)<br />
* [http://www.nginx.org/ Nginx]: A fast and lightweight '''web server''' with a strong focus on high concurrency, performance and low memory usage.<br />
* [http://www.modrails.com/ Passenger] (a.k.a. mod_rails or mod_rack): Supports both Apache and Nginx web servers. It makes deployment of Ruby web applications, such as those built on Ruby on Rails web framework, a breeze.<br />
* [https://rvm.io/ Ruby Version Manager] (RVM): A command-line tool which allows you to easily install, manage, and work with multiple Ruby environments from interpreters to sets of gems. RVM lets you deploy each project with its own completely self-contained and dedicated environment —from the specific version of ruby, all the way down to the precise set of required gems to run your application—.<br />
* [http://sqlite.org/ SQLite]: The default lightweight '''database''' for Ruby on Rails.<br />
<br />
=== Step 0: SQLite ===<br />
<br />
Install {{Pkg|sqlite}}.<br />
<br />
{{note|Of course SQLite is not critical in this setup, you can use MySQL and PostgreSQL as well.}}<br />
<br />
=== Step 1: RVM ===<br />
<br />
Make a multi-user [[RVM]] installation as specified [[RVM#Multi-user_installation|here]].<br />
<br />
In the 'adding users to the rvm group' step, do<br />
# usermod -a -G rvm http<br />
# usermod -a -G rvm nobody<br />
<br />
{{ic|http}} and {{ic|nobody}} are the users related to Nginx and Passenger, respectively.<br />
<br />
{{note|Maybe adding the 'nobody' user to the 'rvm' group is not necessary.}}<br />
<br />
=== Step 2: Rubies ===<br />
<br />
Once you have a working RVM installation in your hands, it is time to install the latest Ruby interpreter<br />
{{Note|During the installation of Ruby patches will be applied. Consider installing the {{ic|base-devel}} group beforehand.}}<br />
<br />
$ rvm install 2.0.0<br />
<br />
{{Note| It may be useful to delete the 'global' gemsets of the environments that have web applications. Their gems might somehow interfere with Passenger. In that case, a {{ic|rvm 2.0.0 do gemset delete global}} is sufficient.}}<br />
<br />
=== Step 3: Nginx with Passenger support ===<br />
<br />
Run the following to allow passenger install nginx:<br />
$ rvm use 2.0.0 <br />
$ gem install passenger<br />
$ rvmsudo passenger-install-nginx-module<br />
<br />
The passenger gem will be put into the ''default'' gemset.<br />
<br />
This will download the sources of Nginx, compile and install it for you. It will guide you through all the process. Note that the default location for Nginx will be {{ic|/opt/nginx}}.<br />
<br />
{{Note|If you encounter a compilation error regarding Boost threads, see [https://bbs.archlinux.org/viewtopic.php?id&#61;139164 this] article.}}<br />
<br />
After completion, add the following two lines into the 'http block' at {{ic|/opt/nginx/conf/nginx.conf}} that look like:<br />
<br />
http { <br />
...<br />
passenger_root /usr/local/rvm/gems/ruby-2.0.0-p353/gems/passenger-3.0.9;<br />
passenger_ruby /usr/local/rvm/wrappers/ruby-2.0.0-p353/ruby;<br />
...<br />
}<br />
<br />
{{Note|This step is currently being done automatically by the installer script.}}<br />
<br />
=== Step 4: Gemsets and Apps ===<br />
<br />
For each Rails application you should have a gemset. Suppose that you want to try [http://refinerycms.com RefineryCMS] against [http://www.browsercms.org BrowserCMS], two open-source Content Management Systems based on Rails.<br />
<br />
Install RefineryCMS first:<br />
<br />
$ rvm use 2.0.0@refinery --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install refinerycms refinerycms-i18n sqlite3<br />
<br />
Deploy a RefineryCMS instance called ''refineria'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo refinerycms refineria<br />
<br />
Install BrowserCMS in a different gemset:<br />
<br />
$ rvm use 2.0.0@browser --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install browsercms sqlite3<br />
<br />
Deploy a BrowserCMS instance called ''navegador'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo browsercms demo navegador<br />
$ cd /srv/http/navegador<br />
$ rvmsudo rake db:install<br />
<br />
=== Passenger for Nginx and Passenger Standalone ===<br />
<br />
Observe that the passenger gem was installed three times and with different intentions; in the environments<br />
* ''2.0.0'' => for Nginx,<br />
* ''2.0.0@refinery'' => Standalone<br />
* ''2.0.0@browser'' => Standalone<br />
<br />
The strategy is to combine Passenger for Nginx with Passenger Standalone. One must first identify the Ruby environment (interpreter plus gemset) that one uses the most; in this setup the Ruby interpreter and the default gemset were selected. One then proceeds with setting up Passenger for Nginx to use that environment (step 3).<br />
* Applications within the chosen environment can be served as in [[#Apache.2FNginx .28using Phusion Passenger.29|Apache/Nginx (using Phusion Passenger)]], page up in this article.<br />
* All applications that are to use a different Ruby version and/or gemset can be served separately through Passenger Standalone and hook into the main web server via a reverse proxy configuration (step 6).<br />
<br />
=== Step 5: .rvmrc files and ownerships ===<br />
<br />
This step is crucial for the correct behaviour of the setup. RVM seeks for .rvmrc files when changing folders; if it finds one, it reads it. In these files normally one stores a line like<br />
rvm <ruby_version>@<gemset_name><br />
so the specified environment is set at the entrance of applications' root folder.<br />
<br />
Create /srv/http/refineria/.rvmrc doing<br />
# echo "rvm ree@refinery" > /srv/http/refineria/.rvmrc<br />
, and /srv/http/navegador/.rvmrc with<br />
# echo "rvm 2.0.0@browser" > /srv/http/navegador/.rvmrc<br />
You have to enter to both application root folders now, because every first time that RVM finds a .rvmrc it asks you if you trust the given file, consequently you must validate the two files you have just created.<br />
<br />
These files aid the programs involved to find the correct gems.<br />
<br />
Apart, if applications' files and folders are not owned by the right user you will face database write-access problems. The use of rvmsudo produces ''root''-owned archives when generated by Rails; in the other hand, ''nobody'' is the user for Passenger —if you have not changed it—: who will use and should posses them. Fix this doing<br />
# chown -R nobody.nobody /srv/http/refineria /srv/http/navegador<br />
<br />
=== Step 6: Reverse proxies ===<br />
<br />
You have to start the Passenger Standalone web servers for your applications. So, do<br />
$ cd /srv/http/refineria<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
and<br />
$ cd /srv/http/navegador<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
. The first time that you run a Passenger Standalone it will perform a minor installation.<br />
<br />
Note that you are using ''unix domain'' sockets instead of the commonly-used ''TCP'' sockets; it turns out that unix domain are significantly faster than TCP sockets.<br />
<br />
{{note|If you are experimenting trouble with unix sockets, changing to TCP should work:<br />
rvmsudo passenger start -a 127.0.0.1 -p 3000 -d<br />
}}<br />
<br />
==== Launch Passenger Standalone daemons at system start-up ====<br />
<br />
''Do you have a script? Please post it here.''<br />
<br />
The systemd script below was made for a Typo blog I host at /srv/http/typo. It is located at /etc/systemd/system/passenger_typo.service. I set the Environment= tags (see "man systemd.exec") from the output of "rvm env". The only exception was PATH=, which I had to combine from my regular PATH and the output of rvm env.<br />
<br />
Note: If you do not set the "WorkingDirectory=" variable to your application folder, passenger will fail to find your app and will subsequently shut itself down.<br />
<br />
<pre><br />
[Unit]<br />
Description=Passenger Standalone Script for Typo<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
WorkingDirectory=/srv/http/typo<br />
PIDFile=/srv/http/typo/tmp/pids/passenger.pid<br />
<br />
Environment=PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo/bin:/usr/local/rvm/gems/ruby-2.0.0-p0@global/bin:/usr/local/rvm/rubies/ruby-2.0.0-p0/bin:/usr/local/rvm/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/bin/core_perl<br />
Environment=rvm_env_string=ruby-2.0.0-p0@typo<br />
Environment=rvm_path=/usr/local/rvm<br />
Environment=rvm_ruby_string=ruby-2.0.0-p0<br />
Environment=rvm_gemset_name=typo<br />
Environment=RUBY_VERSION=ruby-2.0.0-p0<br />
Environment=GEM_HOME=/usr/local/rvm/gems/ruby-2.0.0-p0@typo<br />
Environment=GEM_PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo:/usr/local/rvm/gems/ruby-2.0.0-p0@global<br />
Environment=MY_RUBY_HOME=/usr/local/rvm/rubies/ruby-2.0.0-p0<br />
Environment=IRBRC=/usr/local/rvm/rubies/ruby-2.0.0-p0/.irbrc<br />
<br />
ExecStart=/bin/bash -c "rvmsudo passenger start --socket /srv/http/typo/tmp/sockets/passenger.socket -d"<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
</pre><br />
<br />
=== Step 7: Deployment ===<br />
<br />
==== With subdomains ====<br />
<br />
Once again edit /opt/nginx/conf/nginx.conf to include some vital instructions:<br />
<br />
<pre><br />
## RefineryCMS ##<br />
<br />
server {<br />
server_name refinery.domain.com;<br />
root /srv/http/refineria/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/refineria/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
<br />
## BrowserCMS ##<br />
<br />
server {<br />
server_name browser.domain.com;<br />
root /srv/http/navegador/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/navegador/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
{{note|Or if using TCP sockets, configure the ''proxy_pass'' directive like<br />
<pre>proxy_pass http://127.0.0.1:3000;</pre><br />
}}<br />
<br />
==== Without subdomains ====<br />
<br />
If you for some reason do not want to host each application on its own subdomain but rather in a url like: {{ic|site.com/railsapp}} then you could do something like this in your config:<br />
<br />
<pre><br />
server {<br />
server_name site.com;<br />
#Base for the html files etc<br />
root /srv/http/;<br />
<br />
#First application you want hosted under domain site.com/railsapp<br />
location /railsapp {<br />
root /srv/http/railsapp/public;<br />
#you may need to change passenger_base_uri to be the uri you want to point at, ie:<br />
#passenger_base_uri /railsapp;<br />
#but probably only if you are using the other solution with passenger phusion<br />
proxy_pass http://unix:/srv/http/railsapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
<br />
#Second applicatino you want hosted under domain site.com/anotherapp<br />
location /anotherapp {<br />
root /srv/http/anotherapp/public;<br />
#same thing about the passenger_base_uri here, but with value /anotherapp instead<br />
proxy_pass http://unix:/srv/http/anotherapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
At this point you are in conditions to run Nginx with:<br />
<br />
# systemctl start nginx<br />
<br />
and to access both CMSs through ''refinery.domain.com'' and ''browser.domain.com''.<br />
<br />
=== References ===<br />
<br />
* http://beginrescueend.com/integration/passenger<br />
* http://blog.phusion.nl/2010/09/21/phusion-passenger-running-multiple-ruby-versions<br />
* http://www.ruby-journal.com/how-to-setup-rails-app-with-puma-and-nginx/<br />
* https://www.digitalocean.com/community/tutorials/how-to-deploy-a-rails-app-with-puma-and-nginx-on-ubuntu-14-04<br />
<br />
== See also ==<br />
<br />
* [[Ruby]]<br />
* [[Nginx]]<br />
* [[LAMP]]<br />
* [[MySQL]]<br />
<br />
== References ==<br />
<br />
* Ruby on Rails http://rubyonrails.org/download.<br />
* Mongrel http://mongrel.rubyforge.org.</div>Stbinanhttps://wiki.archlinux.org/index.php?title=Ruby_on_Rails&diff=391496Ruby on Rails2015-08-17T09:37:29Z<p>Stbinan: /* Option 2: by systemd */</p>
<hr />
<div>[[Category:Web server]]<br />
[[zh-CN:Ruby on Rails]]<br />
[http://rubyonrails.org/ Ruby on Rails], often shortened to Rails or RoR, is an open source web application framework for the Ruby programming language. It is intended to be used with an Agile development methodology that is used by web developers for rapid development.<br />
<br />
This document describes how to set up the Ruby on Rails Framework on an Arch Linux system.<br />
<br />
== Installation ==<br />
<br />
Ruby on Rails requires [[Ruby]] to be installed, so read that article first for installation instructions. The {{pkg|nodejs}} package is also required.<br />
<br />
Ruby on Rails itself can be installed multiple ways:<br />
<br />
=== Option A: via RubyGems ===<br />
<br />
{{Note|You can also install Rails system-wide using Gems. To do this, run the following commands as root and append them with {{ic|--no-user-install}}. Please read [[Ruby#Installing gems per-user or system-wide]] for possible dangers of using RubyGem in this way.}}<br />
<br />
The following command will install Rails for the current user:<br />
$ gem install rails<br />
<br />
Building the documentation takes a while. If you want to skip it, append {{ic|--no-document}} to the install command.<br />
$ gem install rails --no-document<br />
<br />
gem is a package manager for Ruby modules, somewhat like pacman is to Arch Linux. To update your gems, simply run:<br />
$ gem update<br />
<br />
=== Option B: via pacgem ===<br />
<br />
You can install Rails using {{AUR|pacgem}} from the [[AUR]]. Pacgem automatically creates PKGBUILDs and Arch packages for each of the gems. These packages will then be installed using pacman.<br />
# pacgem rails<br />
<br />
The gem packages can be updated with<br />
# pacgem -u<br />
<br />
=== Option C: from the AUR ===<br />
<br />
{{Warning|This is not recommended, as this might not include the latest Rails version, and additional dependencies may be introduced that may require you to run {{Ic|gem install}} anyway.}}<br />
<br />
There is a {{AUR|ruby-rails}} package available in the [[AUR]].<br />
<br />
=== Option D: from Quarry binary repository ===<br />
<br />
[[pacman|Install]] ''ruby-rails'' from the unofficial [[Unofficial user repositories#quarry|quarry]] repository.<br />
<br />
== Configuration ==<br />
<br />
Rails is bundled with a basic HTTP server called WeBrick. You can create a test application to test it. First, create an application with the rails command:<br />
<br />
$ rails new testapp_name<br />
<br />
{{Note|If you get an error like {{ic|Errno::ENOENT: No such file or directory (...) An error occurred while installing x, and Bundler cannot continue.}}, you might have to configure [[Ruby#Bundler|Bundler]] so that it installs gems per-user and not system-wide. Alternatively, run {{ic|# rails new testapp_name}} once as root. If it has completed successfully, delete {{ic|testapp_name/}} and run {{ic|$ rails new testapp_name}} again as a regular user.}}<br />
{{Note|If you get an error message like this:<br />
{{ic|... FetchError: SSL_connect returned&#61;1 errno&#61; 0 state&#61;SSLv2/v3 read server hello A: sslv3 alert handshake<br />
failure <nowiki>(https://s3.amazonaws.com/ production.s3.rubygems.org/gems/rake-10.0.3.gem)</nowiki> }}<br />
install {{Pkg|nodejs}} and try again.}}<br />
<br />
This creates a new folder inside your current working directory. <br />
<br />
$ cd testapp_name<br />
<br />
Next start the web server. It listens on port 3000 by default:<br />
<br />
$ rails server<br />
<br />
Now visit the testapp_name website on your local machine by opening <nowiki>http://localhost:3000</nowiki> in your browser<br />
{{Note|If Ruby complains about not being able to find a JavaScript runtime, install {{Pkg|nodejs}}.}}<br />
<br />
A test-page should shown greeting you "Welcome aboard".<br />
<br />
== Application servers ==<br />
<br />
The built-in Ruby On Rails HTTP server (WeBrick) is convenient for basic development, but it is not recommended for production use. Instead, you should use an application server such as [[#Thin]], [[#Unicorn]] or [[#Apache/Nginx (using Phusion Passenger)|Phusion Passenger]].<br />
<br />
=== Thin ===<br />
<br />
[http://code.macournoyer.com/thin/ Thin] is a fast and very simple Ruby web server.<br />
<br />
First install thin gem:<br />
$ gem install thin<br />
<br />
Then start it using:<br />
$ thin start<br />
<br />
=== Unicorn ===<br />
<br />
Unicorn is an application server that cannot talk directly to clients. Instead, a web server must sit between clients and Unicorn, proxying requests as needed. [http://unicorn.bogomips.org/ Unicorn] is loosely based on Mongrel. It is used by Github, and it uses an architecture that tries hard to find the best child for handling a request. [https://github.com/blog/517-unicorn Explanation of differences between Unicorn and Mongrel].<br />
<br />
Install the Unicorn gem:<br />
# gem install unicorn<br />
<br />
Then create a configuration file for your application in {{ic|/etc/unicorn/}}. For example; here is a configuration example (Based on [http://www.warden.pl/2011/01/07/running-redmine-under-unicorn-in-debian/]) for Redmine:<br />
<br />
{{hc|/etc/unicorn/redmine.ru|<nowiki><br />
working_directory "/srv/http/redmine"<br />
pid "/tmp/redmine.pid"<br />
<br />
preload_app true<br />
timeout 60<br />
worker_processes 4<br />
listen 4000<br />
stderr_path('/var/log/unicorn.log')<br />
<br />
GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true<br />
<br />
after_fork do |server, worker|<br />
#start the worker on port 4000, 4001, 4002 etc...<br />
addr = "0.0.0.0:#{4000 + worker.nr}"<br />
# infinite tries to start the worker<br />
server.listen(addr, :tries => -1, :delay => -1, :backlog => 128)<br />
<br />
#Drop privileges if running as root<br />
worker.user('nobody', 'nobody') if Process.euid == 0<br />
end<br />
</nowiki>}}<br />
<br />
Start it using:<br />
# /usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
==== Systemd service ====<br />
<br />
Put the following contents in {{ic|/etc/systemd/system/unicorn.service}}:<br />
{{hc|/etc/systemd/system/unicorn.service|2=<br />
[Unit]<br />
Description=Unicorn application server<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
User=redmine<br />
ExecStart=/usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
}}<br />
<br />
You can now easily start and stop unicorn using systemctl<br />
<br />
==== Nginx Configuration ====<br />
<br />
After setting up [[Nginx]], configure unicorn as an upstream server using something like this (Warning: this is a stripped example. It probably does not work without additional configuration):<br />
{{bc|1=<br />
http {<br />
upstream unicorn {<br />
server 127.0.0.1:4000 fail_timeout=0;<br />
server 127.0.0.1:4001 fail_timeout=0;<br />
server 127.0.0.1:4002 fail_timeout=0;<br />
server 127.0.0.1:4003 fail_timeout=0;<br />
}<br />
<br />
server {<br />
listen 80 default;<br />
server_name YOURHOSTNAMEHERE;<br />
<br />
location / {<br />
root /srv/http/redmine/public;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
proxy_pass http://unicorn;<br />
}<br />
}<br />
}<br />
}}<br />
<br />
=== Apache/Nginx (using Phusion Passenger) ===<br />
<br />
[http://www.modrails.com/ Passenger] also known as {{ic|mod_rails}} is a module available for [[Nginx]] and [[Apache]], that greatly simplifies setting up a Rails server environment. Nginx does not support modules as Apache and has to be compiled with {{ic|mod_rails}} in order to support Passenger; let Passenger compile it for you. As for Apache, let Passenger set up the module for you.<br />
<br />
Start by installing the 'passenger' gem:<br />
# gem install passenger<br />
<br />
If you are aiming to use [[Apache]], run:<br />
# passenger-install-apache2-module<br />
<br />
In case a rails application is deployed with a sub-URI, like http://example.com/yourapplication, some additional configuration is required, see [http://www.modrails.com/documentation/Users%20guide%20Apache.html#deploying_rails_to_sub_uri the modrails documentation]<br />
<br />
For [[Nginx]]:<br />
# passenger-install-nginx-module<br />
<br />
The installer will provide you with any additional information regarding the installation (such as installing additional libraries).<br />
<br />
To serve an application with Nginx, configure it as follows:<br />
<pre><br />
server {<br />
server_name app.example.org;<br />
root path_to_app/public; # Be sure to point to 'public' folder!<br />
passenger_enabled on;<br />
rails_env development; # Rails environment.<br />
}<br />
</pre><br />
<br />
=== Puma (with Nginx as reverse proxy server) ===<br />
<br />
[http://puma.io/ Puma] ([https://github.com/puma/puma Github Page]) is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications, and is considered the replacement for Webrick and Mongrel. It was designed to be the go-to server for Rubinius, but also works well with JRuby and MRI. While reverse proxy server would acts as a load balancer that routes all external requests to a pool of web apps.<br />
<br />
For a webserver it is better to use a server user and group, check [[Users_and_groups#Example_adding_a_user]], below use {{ic|rails}} as user name and {{ic|server}} as group name, also {{ic|my_app}} as rails app name.<br />
<br />
Start by copying your app to /var/www/my_app. And set new ownership with<br />
# cd /var/www/<br />
# chown -R rails:server my_app<br />
<br />
and permission for user with<br />
# chmod -R 775 my_app<br />
<br />
Then add puma gem in the Gemfile and install with<br />
$ cd my_app <br />
$ bundle install<br />
<br />
Also install {{ic|nginx}} by pacman.<br />
<br />
Under your app folder, create sockets, pid and log folder with<br />
$ mkdir -p shared/pids shared/sockets shared/log<br />
<br />
Backup nginx.conf with<br />
# cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup<br />
<br />
Then create a new nginx.conf file with your favorite editor, copy codes below and modify as you like:<br />
<pre><br />
#user html;<br />
worker_processes 1; # this may connect with the worker numbers puma can use.<br />
<br />
#error_log logs/error.log;<br />
#error_log logs/error.log notice;<br />
#error_log logs/error.log info;<br />
<br />
#pid logs/nginx.pid;<br />
<br />
<br />
events {<br />
worker_connections 1024;<br />
}<br />
<br />
http {<br />
upstream app {<br />
# Path to Puma SOCK file, as defined previously<br />
server unix:/var/www/my_app/shared/sockets/puma.sock;<br />
}<br />
<br />
server {<br />
listen 80;<br />
server_name localhost; # or your server name<br />
<br />
root /var/www/my_app/public;<br />
<br />
try_files $uri/index.html $uri @app;<br />
<br />
location @app {<br />
proxy_pass http://app;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
}<br />
<br />
error_page 500 502 503 504 /500.html;<br />
client_max_body_size 4G;<br />
keepalive_timeout 10;<br />
}<br />
}</pre><br />
<br />
Start nginx service with<br />
# systemctl start nginx<br />
<br />
<br />
There are several ways to start puma server, two ways are recommended below:<br />
<br />
==== Option A: With config file ====<br />
<br />
Create file {{ic|config/puma.rb}}, copy codes below and modify as you like:<br />
<pre><br />
# Change to match your CPU core count<br />
# You can check available worker numbers with $ grep -c processor /proc/cpuinfo<br />
# also see the comment in the nginx.conf<br />
workers 2<br />
<br />
# Min and Max threads per worker<br />
#threads 1, 6<br />
<br />
app_dir = File.expand_path("../..", __FILE__)<br />
shared_dir = "#{app_dir}/shared"<br />
<br />
# Default to production<br />
#rails_env = ENV['RAILS_ENV'] || "production"<br />
#environment rails_env<br />
<br />
# Set up socket location<br />
bind "unix://#{shared_dir}/sockets/puma.sock"<br />
<br />
# Logging<br />
#stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true<br />
<br />
# Set master PID and state locations<br />
pidfile "#{shared_dir}/pids/puma.pid"<br />
#state_path "#{shared_dir}/pids/puma.state"<br />
#activate_control_app<br />
<br />
#on_worker_boot do<br />
# require "active_record"<br />
# ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished<br />
# ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])<br />
#end</pre><br />
<br />
and start server with<br />
$ bundle exec puma -C config/puma.rb<br />
<br />
You can also run it in background with parameter {{ic|-d}} and check with<br />
$ ps aux| grep puma<br />
when you want to {{ic|kill}} it.<br />
<br />
==== Option 2: by systemd ====<br />
<br />
Create a new systemd unit {{ic|puma.service}} under /usr/lib/systemd/system/ and copy codes below<br />
<pre><br />
[Unit]<br />
Description=Puma application server<br />
After=network.target<br />
<br />
[Service]<br />
WorkingDirectory=/var/www/my_app<br />
#Environment=RAILS_ENV=production<br />
User=rails<br />
PIDFile=/var/www/my_app/shared/pids/puma.pid<br />
ExecStart=/home/rails/.gem/ruby/2.2.0/bin/bundle exec \<br />
/home/rails/.gem/ruby/2.2.0/bin/puma \<br />
-b unix:///var/www/my_app/shared/sockets/puma.sock \<br />
--pidfile /var/www/my_app/shared/pids/puma.pid<br />
<br />
[Install]<br />
WantedBy=multi-user.target</pre><br />
<br />
Then start puma with<br />
# systemctl start puma<br />
<br />
<br />
For further reading take a look at [[Ruby_on_Rails#References]]<br />
<br />
== Databases ==<br />
<br />
Most web applications will need to interact with some sort of database. ActiveRecord (the ORM used by Rails to provide database abstraction) supports several database vendors, the most popular of which are MySQL, SQLite, and PostgreSQL.<br />
<br />
=== SQLite ===<br />
<br />
SQLite is the default lightweight database for Ruby on Rails. To enable SQLite, simply install {{Pkg|sqlite}}.<br />
<br />
=== PostgreSQL ===<br />
<br />
Install {{Pkg|postgresql}}.<br />
<br />
=== MySQL ===<br />
<br />
First, install and configure a MySQL server. Please refer to [[MySQL]] on how to do this.<br />
<br />
A gem with some native extensions is required, probably best installed as root:<br />
# gem install mysql<br />
<br />
You can generate a rails application configured for MySQL by using the {{ic|-d}} parameter:<br />
$ rails new testapp_name -d mysql<br />
<br />
You then need to edit {{ic|config/database.yml}}. Rails uses different databases for development, testing, production and other environments. Here is an example development configuration for MySQL running on localhost:<br />
<br />
development:<br />
adapter: mysql<br />
database: my_application_database<br />
username: development<br />
password: my_secret_password<br />
<br />
Note that you do not have to actually create the database using MySQL, as this can be done via Rails with:<br />
# rake db:create<br />
<br />
If no errors are shown, then your database has been created and Rails can talk to your MySQL database.<br />
<br />
== The Perfect Rails Setup ==<br />
<br />
''Phusion Passenger running multiple Ruby versions.''<br />
<br />
* [https://www.archlinux.org/ Arch Linux]: A simple, lightweight distribution. ;)<br />
* [http://www.nginx.org/ Nginx]: A fast and lightweight '''web server''' with a strong focus on high concurrency, performance and low memory usage.<br />
* [http://www.modrails.com/ Passenger] (a.k.a. mod_rails or mod_rack): Supports both Apache and Nginx web servers. It makes deployment of Ruby web applications, such as those built on Ruby on Rails web framework, a breeze.<br />
* [https://rvm.io/ Ruby Version Manager] (RVM): A command-line tool which allows you to easily install, manage, and work with multiple Ruby environments from interpreters to sets of gems. RVM lets you deploy each project with its own completely self-contained and dedicated environment —from the specific version of ruby, all the way down to the precise set of required gems to run your application—.<br />
* [http://sqlite.org/ SQLite]: The default lightweight '''database''' for Ruby on Rails.<br />
<br />
=== Step 0: SQLite ===<br />
<br />
Install {{Pkg|sqlite}}.<br />
<br />
{{note|Of course SQLite is not critical in this setup, you can use MySQL and PostgreSQL as well.}}<br />
<br />
=== Step 1: RVM ===<br />
<br />
Make a multi-user [[RVM]] installation as specified [[RVM#Multi-user_installation|here]].<br />
<br />
In the 'adding users to the rvm group' step, do<br />
# usermod -a -G rvm http<br />
# usermod -a -G rvm nobody<br />
<br />
{{ic|http}} and {{ic|nobody}} are the users related to Nginx and Passenger, respectively.<br />
<br />
{{note|Maybe adding the 'nobody' user to the 'rvm' group is not necessary.}}<br />
<br />
=== Step 2: Rubies ===<br />
<br />
Once you have a working RVM installation in your hands, it is time to install the latest Ruby interpreter<br />
{{Note|During the installation of Ruby patches will be applied. Consider installing the {{ic|base-devel}} group beforehand.}}<br />
<br />
$ rvm install 2.0.0<br />
<br />
{{Note| It may be useful to delete the 'global' gemsets of the environments that have web applications. Their gems might somehow interfere with Passenger. In that case, a {{ic|rvm 2.0.0 do gemset delete global}} is sufficient.}}<br />
<br />
=== Step 3: Nginx with Passenger support ===<br />
<br />
Run the following to allow passenger install nginx:<br />
$ rvm use 2.0.0 <br />
$ gem install passenger<br />
$ rvmsudo passenger-install-nginx-module<br />
<br />
The passenger gem will be put into the ''default'' gemset.<br />
<br />
This will download the sources of Nginx, compile and install it for you. It will guide you through all the process. Note that the default location for Nginx will be {{ic|/opt/nginx}}.<br />
<br />
{{Note|If you encounter a compilation error regarding Boost threads, see [https://bbs.archlinux.org/viewtopic.php?id&#61;139164 this] article.}}<br />
<br />
After completion, add the following two lines into the 'http block' at {{ic|/opt/nginx/conf/nginx.conf}} that look like:<br />
<br />
http { <br />
...<br />
passenger_root /usr/local/rvm/gems/ruby-2.0.0-p353/gems/passenger-3.0.9;<br />
passenger_ruby /usr/local/rvm/wrappers/ruby-2.0.0-p353/ruby;<br />
...<br />
}<br />
<br />
{{Note|This step is currently being done automatically by the installer script.}}<br />
<br />
=== Step 4: Gemsets and Apps ===<br />
<br />
For each Rails application you should have a gemset. Suppose that you want to try [http://refinerycms.com RefineryCMS] against [http://www.browsercms.org BrowserCMS], two open-source Content Management Systems based on Rails.<br />
<br />
Install RefineryCMS first:<br />
<br />
$ rvm use 2.0.0@refinery --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install refinerycms refinerycms-i18n sqlite3<br />
<br />
Deploy a RefineryCMS instance called ''refineria'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo refinerycms refineria<br />
<br />
Install BrowserCMS in a different gemset:<br />
<br />
$ rvm use 2.0.0@browser --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install browsercms sqlite3<br />
<br />
Deploy a BrowserCMS instance called ''navegador'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo browsercms demo navegador<br />
$ cd /srv/http/navegador<br />
$ rvmsudo rake db:install<br />
<br />
=== Passenger for Nginx and Passenger Standalone ===<br />
<br />
Observe that the passenger gem was installed three times and with different intentions; in the environments<br />
* ''2.0.0'' => for Nginx,<br />
* ''2.0.0@refinery'' => Standalone<br />
* ''2.0.0@browser'' => Standalone<br />
<br />
The strategy is to combine Passenger for Nginx with Passenger Standalone. One must first identify the Ruby environment (interpreter plus gemset) that one uses the most; in this setup the Ruby interpreter and the default gemset were selected. One then proceeds with setting up Passenger for Nginx to use that environment (step 3).<br />
* Applications within the chosen environment can be served as in [[#Apache.2FNginx .28using Phusion Passenger.29|Apache/Nginx (using Phusion Passenger)]], page up in this article.<br />
* All applications that are to use a different Ruby version and/or gemset can be served separately through Passenger Standalone and hook into the main web server via a reverse proxy configuration (step 6).<br />
<br />
=== Step 5: .rvmrc files and ownerships ===<br />
<br />
This step is crucial for the correct behaviour of the setup. RVM seeks for .rvmrc files when changing folders; if it finds one, it reads it. In these files normally one stores a line like<br />
rvm <ruby_version>@<gemset_name><br />
so the specified environment is set at the entrance of applications' root folder.<br />
<br />
Create /srv/http/refineria/.rvmrc doing<br />
# echo "rvm ree@refinery" > /srv/http/refineria/.rvmrc<br />
, and /srv/http/navegador/.rvmrc with<br />
# echo "rvm 2.0.0@browser" > /srv/http/navegador/.rvmrc<br />
You have to enter to both application root folders now, because every first time that RVM finds a .rvmrc it asks you if you trust the given file, consequently you must validate the two files you have just created.<br />
<br />
These files aid the programs involved to find the correct gems.<br />
<br />
Apart, if applications' files and folders are not owned by the right user you will face database write-access problems. The use of rvmsudo produces ''root''-owned archives when generated by Rails; in the other hand, ''nobody'' is the user for Passenger —if you have not changed it—: who will use and should posses them. Fix this doing<br />
# chown -R nobody.nobody /srv/http/refineria /srv/http/navegador<br />
<br />
=== Step 6: Reverse proxies ===<br />
<br />
You have to start the Passenger Standalone web servers for your applications. So, do<br />
$ cd /srv/http/refineria<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
and<br />
$ cd /srv/http/navegador<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
. The first time that you run a Passenger Standalone it will perform a minor installation.<br />
<br />
Note that you are using ''unix domain'' sockets instead of the commonly-used ''TCP'' sockets; it turns out that unix domain are significantly faster than TCP sockets.<br />
<br />
{{note|If you are experimenting trouble with unix sockets, changing to TCP should work:<br />
rvmsudo passenger start -a 127.0.0.1 -p 3000 -d<br />
}}<br />
<br />
==== Launch Passenger Standalone daemons at system start-up ====<br />
<br />
''Do you have a script? Please post it here.''<br />
<br />
The systemd script below was made for a Typo blog I host at /srv/http/typo. It is located at /etc/systemd/system/passenger_typo.service. I set the Environment= tags (see "man systemd.exec") from the output of "rvm env". The only exception was PATH=, which I had to combine from my regular PATH and the output of rvm env.<br />
<br />
Note: If you do not set the "WorkingDirectory=" variable to your application folder, passenger will fail to find your app and will subsequently shut itself down.<br />
<br />
<pre><br />
[Unit]<br />
Description=Passenger Standalone Script for Typo<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
WorkingDirectory=/srv/http/typo<br />
PIDFile=/srv/http/typo/tmp/pids/passenger.pid<br />
<br />
Environment=PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo/bin:/usr/local/rvm/gems/ruby-2.0.0-p0@global/bin:/usr/local/rvm/rubies/ruby-2.0.0-p0/bin:/usr/local/rvm/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/bin/core_perl<br />
Environment=rvm_env_string=ruby-2.0.0-p0@typo<br />
Environment=rvm_path=/usr/local/rvm<br />
Environment=rvm_ruby_string=ruby-2.0.0-p0<br />
Environment=rvm_gemset_name=typo<br />
Environment=RUBY_VERSION=ruby-2.0.0-p0<br />
Environment=GEM_HOME=/usr/local/rvm/gems/ruby-2.0.0-p0@typo<br />
Environment=GEM_PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo:/usr/local/rvm/gems/ruby-2.0.0-p0@global<br />
Environment=MY_RUBY_HOME=/usr/local/rvm/rubies/ruby-2.0.0-p0<br />
Environment=IRBRC=/usr/local/rvm/rubies/ruby-2.0.0-p0/.irbrc<br />
<br />
ExecStart=/bin/bash -c "rvmsudo passenger start --socket /srv/http/typo/tmp/sockets/passenger.socket -d"<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
</pre><br />
<br />
=== Step 7: Deployment ===<br />
<br />
==== With subdomains ====<br />
<br />
Once again edit /opt/nginx/conf/nginx.conf to include some vital instructions:<br />
<br />
<pre><br />
## RefineryCMS ##<br />
<br />
server {<br />
server_name refinery.domain.com;<br />
root /srv/http/refineria/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/refineria/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
<br />
## BrowserCMS ##<br />
<br />
server {<br />
server_name browser.domain.com;<br />
root /srv/http/navegador/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/navegador/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
{{note|Or if using TCP sockets, configure the ''proxy_pass'' directive like<br />
<pre>proxy_pass http://127.0.0.1:3000;</pre><br />
}}<br />
<br />
==== Without subdomains ====<br />
<br />
If you for some reason do not want to host each application on its own subdomain but rather in a url like: {{ic|site.com/railsapp}} then you could do something like this in your config:<br />
<br />
<pre><br />
server {<br />
server_name site.com;<br />
#Base for the html files etc<br />
root /srv/http/;<br />
<br />
#First application you want hosted under domain site.com/railsapp<br />
location /railsapp {<br />
root /srv/http/railsapp/public;<br />
#you may need to change passenger_base_uri to be the uri you want to point at, ie:<br />
#passenger_base_uri /railsapp;<br />
#but probably only if you are using the other solution with passenger phusion<br />
proxy_pass http://unix:/srv/http/railsapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
<br />
#Second applicatino you want hosted under domain site.com/anotherapp<br />
location /anotherapp {<br />
root /srv/http/anotherapp/public;<br />
#same thing about the passenger_base_uri here, but with value /anotherapp instead<br />
proxy_pass http://unix:/srv/http/anotherapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
At this point you are in conditions to run Nginx with:<br />
<br />
# systemctl start nginx<br />
<br />
and to access both CMSs through ''refinery.domain.com'' and ''browser.domain.com''.<br />
<br />
=== References ===<br />
<br />
* http://beginrescueend.com/integration/passenger<br />
* http://blog.phusion.nl/2010/09/21/phusion-passenger-running-multiple-ruby-versions<br />
* http://www.ruby-journal.com/how-to-setup-rails-app-with-puma-and-nginx/<br />
* https://www.digitalocean.com/community/tutorials/how-to-deploy-a-rails-app-with-puma-and-nginx-on-ubuntu-14-04<br />
<br />
== See also ==<br />
<br />
* [[Ruby]]<br />
* [[Nginx]]<br />
* [[LAMP]]<br />
* [[MySQL]]<br />
<br />
== References ==<br />
<br />
* Ruby on Rails http://rubyonrails.org/download.<br />
* Mongrel http://mongrel.rubyforge.org.</div>Stbinanhttps://wiki.archlinux.org/index.php?title=Ruby_on_Rails&diff=391495Ruby on Rails2015-08-17T09:36:36Z<p>Stbinan: /* References */</p>
<hr />
<div>[[Category:Web server]]<br />
[[zh-CN:Ruby on Rails]]<br />
[http://rubyonrails.org/ Ruby on Rails], often shortened to Rails or RoR, is an open source web application framework for the Ruby programming language. It is intended to be used with an Agile development methodology that is used by web developers for rapid development.<br />
<br />
This document describes how to set up the Ruby on Rails Framework on an Arch Linux system.<br />
<br />
== Installation ==<br />
<br />
Ruby on Rails requires [[Ruby]] to be installed, so read that article first for installation instructions. The {{pkg|nodejs}} package is also required.<br />
<br />
Ruby on Rails itself can be installed multiple ways:<br />
<br />
=== Option A: via RubyGems ===<br />
<br />
{{Note|You can also install Rails system-wide using Gems. To do this, run the following commands as root and append them with {{ic|--no-user-install}}. Please read [[Ruby#Installing gems per-user or system-wide]] for possible dangers of using RubyGem in this way.}}<br />
<br />
The following command will install Rails for the current user:<br />
$ gem install rails<br />
<br />
Building the documentation takes a while. If you want to skip it, append {{ic|--no-document}} to the install command.<br />
$ gem install rails --no-document<br />
<br />
gem is a package manager for Ruby modules, somewhat like pacman is to Arch Linux. To update your gems, simply run:<br />
$ gem update<br />
<br />
=== Option B: via pacgem ===<br />
<br />
You can install Rails using {{AUR|pacgem}} from the [[AUR]]. Pacgem automatically creates PKGBUILDs and Arch packages for each of the gems. These packages will then be installed using pacman.<br />
# pacgem rails<br />
<br />
The gem packages can be updated with<br />
# pacgem -u<br />
<br />
=== Option C: from the AUR ===<br />
<br />
{{Warning|This is not recommended, as this might not include the latest Rails version, and additional dependencies may be introduced that may require you to run {{Ic|gem install}} anyway.}}<br />
<br />
There is a {{AUR|ruby-rails}} package available in the [[AUR]].<br />
<br />
=== Option D: from Quarry binary repository ===<br />
<br />
[[pacman|Install]] ''ruby-rails'' from the unofficial [[Unofficial user repositories#quarry|quarry]] repository.<br />
<br />
== Configuration ==<br />
<br />
Rails is bundled with a basic HTTP server called WeBrick. You can create a test application to test it. First, create an application with the rails command:<br />
<br />
$ rails new testapp_name<br />
<br />
{{Note|If you get an error like {{ic|Errno::ENOENT: No such file or directory (...) An error occurred while installing x, and Bundler cannot continue.}}, you might have to configure [[Ruby#Bundler|Bundler]] so that it installs gems per-user and not system-wide. Alternatively, run {{ic|# rails new testapp_name}} once as root. If it has completed successfully, delete {{ic|testapp_name/}} and run {{ic|$ rails new testapp_name}} again as a regular user.}}<br />
{{Note|If you get an error message like this:<br />
{{ic|... FetchError: SSL_connect returned&#61;1 errno&#61; 0 state&#61;SSLv2/v3 read server hello A: sslv3 alert handshake<br />
failure <nowiki>(https://s3.amazonaws.com/ production.s3.rubygems.org/gems/rake-10.0.3.gem)</nowiki> }}<br />
install {{Pkg|nodejs}} and try again.}}<br />
<br />
This creates a new folder inside your current working directory. <br />
<br />
$ cd testapp_name<br />
<br />
Next start the web server. It listens on port 3000 by default:<br />
<br />
$ rails server<br />
<br />
Now visit the testapp_name website on your local machine by opening <nowiki>http://localhost:3000</nowiki> in your browser<br />
{{Note|If Ruby complains about not being able to find a JavaScript runtime, install {{Pkg|nodejs}}.}}<br />
<br />
A test-page should shown greeting you "Welcome aboard".<br />
<br />
== Application servers ==<br />
<br />
The built-in Ruby On Rails HTTP server (WeBrick) is convenient for basic development, but it is not recommended for production use. Instead, you should use an application server such as [[#Thin]], [[#Unicorn]] or [[#Apache/Nginx (using Phusion Passenger)|Phusion Passenger]].<br />
<br />
=== Thin ===<br />
<br />
[http://code.macournoyer.com/thin/ Thin] is a fast and very simple Ruby web server.<br />
<br />
First install thin gem:<br />
$ gem install thin<br />
<br />
Then start it using:<br />
$ thin start<br />
<br />
=== Unicorn ===<br />
<br />
Unicorn is an application server that cannot talk directly to clients. Instead, a web server must sit between clients and Unicorn, proxying requests as needed. [http://unicorn.bogomips.org/ Unicorn] is loosely based on Mongrel. It is used by Github, and it uses an architecture that tries hard to find the best child for handling a request. [https://github.com/blog/517-unicorn Explanation of differences between Unicorn and Mongrel].<br />
<br />
Install the Unicorn gem:<br />
# gem install unicorn<br />
<br />
Then create a configuration file for your application in {{ic|/etc/unicorn/}}. For example; here is a configuration example (Based on [http://www.warden.pl/2011/01/07/running-redmine-under-unicorn-in-debian/]) for Redmine:<br />
<br />
{{hc|/etc/unicorn/redmine.ru|<nowiki><br />
working_directory "/srv/http/redmine"<br />
pid "/tmp/redmine.pid"<br />
<br />
preload_app true<br />
timeout 60<br />
worker_processes 4<br />
listen 4000<br />
stderr_path('/var/log/unicorn.log')<br />
<br />
GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true<br />
<br />
after_fork do |server, worker|<br />
#start the worker on port 4000, 4001, 4002 etc...<br />
addr = "0.0.0.0:#{4000 + worker.nr}"<br />
# infinite tries to start the worker<br />
server.listen(addr, :tries => -1, :delay => -1, :backlog => 128)<br />
<br />
#Drop privileges if running as root<br />
worker.user('nobody', 'nobody') if Process.euid == 0<br />
end<br />
</nowiki>}}<br />
<br />
Start it using:<br />
# /usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
==== Systemd service ====<br />
<br />
Put the following contents in {{ic|/etc/systemd/system/unicorn.service}}:<br />
{{hc|/etc/systemd/system/unicorn.service|2=<br />
[Unit]<br />
Description=Unicorn application server<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
User=redmine<br />
ExecStart=/usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
}}<br />
<br />
You can now easily start and stop unicorn using systemctl<br />
<br />
==== Nginx Configuration ====<br />
<br />
After setting up [[Nginx]], configure unicorn as an upstream server using something like this (Warning: this is a stripped example. It probably does not work without additional configuration):<br />
{{bc|1=<br />
http {<br />
upstream unicorn {<br />
server 127.0.0.1:4000 fail_timeout=0;<br />
server 127.0.0.1:4001 fail_timeout=0;<br />
server 127.0.0.1:4002 fail_timeout=0;<br />
server 127.0.0.1:4003 fail_timeout=0;<br />
}<br />
<br />
server {<br />
listen 80 default;<br />
server_name YOURHOSTNAMEHERE;<br />
<br />
location / {<br />
root /srv/http/redmine/public;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
proxy_pass http://unicorn;<br />
}<br />
}<br />
}<br />
}}<br />
<br />
=== Apache/Nginx (using Phusion Passenger) ===<br />
<br />
[http://www.modrails.com/ Passenger] also known as {{ic|mod_rails}} is a module available for [[Nginx]] and [[Apache]], that greatly simplifies setting up a Rails server environment. Nginx does not support modules as Apache and has to be compiled with {{ic|mod_rails}} in order to support Passenger; let Passenger compile it for you. As for Apache, let Passenger set up the module for you.<br />
<br />
Start by installing the 'passenger' gem:<br />
# gem install passenger<br />
<br />
If you are aiming to use [[Apache]], run:<br />
# passenger-install-apache2-module<br />
<br />
In case a rails application is deployed with a sub-URI, like http://example.com/yourapplication, some additional configuration is required, see [http://www.modrails.com/documentation/Users%20guide%20Apache.html#deploying_rails_to_sub_uri the modrails documentation]<br />
<br />
For [[Nginx]]:<br />
# passenger-install-nginx-module<br />
<br />
The installer will provide you with any additional information regarding the installation (such as installing additional libraries).<br />
<br />
To serve an application with Nginx, configure it as follows:<br />
<pre><br />
server {<br />
server_name app.example.org;<br />
root path_to_app/public; # Be sure to point to 'public' folder!<br />
passenger_enabled on;<br />
rails_env development; # Rails environment.<br />
}<br />
</pre><br />
<br />
=== Puma (with Nginx as reverse proxy server) ===<br />
<br />
[http://puma.io/ Puma] ([https://github.com/puma/puma Github Page]) is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications, and is considered the replacement for Webrick and Mongrel. It was designed to be the go-to server for Rubinius, but also works well with JRuby and MRI. While reverse proxy server would acts as a load balancer that routes all external requests to a pool of web apps.<br />
<br />
For a webserver it is better to use a server user and group, check [[Users_and_groups#Example_adding_a_user]], below use {{ic|rails}} as user name and {{ic|server}} as group name, also {{ic|my_app}} as rails app name.<br />
<br />
Start by copying your app to /var/www/my_app. And set new ownership with<br />
# cd /var/www/<br />
# chown -R rails:server my_app<br />
<br />
and permission for user with<br />
# chmod -R 775 my_app<br />
<br />
Then add puma gem in the Gemfile and install with<br />
$ cd my_app <br />
$ bundle install<br />
<br />
Also install {{ic|nginx}} by pacman.<br />
<br />
Under your app folder, create sockets, pid and log folder with<br />
$ mkdir -p shared/pids shared/sockets shared/log<br />
<br />
Backup nginx.conf with<br />
# cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup<br />
<br />
Then create a new nginx.conf file with your favorite editor, copy codes below and modify as you like:<br />
<pre><br />
#user html;<br />
worker_processes 1; # this may connect with the worker numbers puma can use.<br />
<br />
#error_log logs/error.log;<br />
#error_log logs/error.log notice;<br />
#error_log logs/error.log info;<br />
<br />
#pid logs/nginx.pid;<br />
<br />
<br />
events {<br />
worker_connections 1024;<br />
}<br />
<br />
http {<br />
upstream app {<br />
# Path to Puma SOCK file, as defined previously<br />
server unix:/var/www/my_app/shared/sockets/puma.sock;<br />
}<br />
<br />
server {<br />
listen 80;<br />
server_name localhost; # or your server name<br />
<br />
root /var/www/my_app/public;<br />
<br />
try_files $uri/index.html $uri @app;<br />
<br />
location @app {<br />
proxy_pass http://app;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
}<br />
<br />
error_page 500 502 503 504 /500.html;<br />
client_max_body_size 4G;<br />
keepalive_timeout 10;<br />
}<br />
}</pre><br />
<br />
Start nginx service with<br />
# systemctl start nginx<br />
<br />
<br />
There are several ways to start puma server, two ways are recommended below:<br />
<br />
==== Option A: With config file ====<br />
<br />
Create file {{ic|config/puma.rb}}, copy codes below and modify as you like:<br />
<pre><br />
# Change to match your CPU core count<br />
# You can check available worker numbers with $ grep -c processor /proc/cpuinfo<br />
# also see the comment in the nginx.conf<br />
workers 2<br />
<br />
# Min and Max threads per worker<br />
#threads 1, 6<br />
<br />
app_dir = File.expand_path("../..", __FILE__)<br />
shared_dir = "#{app_dir}/shared"<br />
<br />
# Default to production<br />
#rails_env = ENV['RAILS_ENV'] || "production"<br />
#environment rails_env<br />
<br />
# Set up socket location<br />
bind "unix://#{shared_dir}/sockets/puma.sock"<br />
<br />
# Logging<br />
#stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true<br />
<br />
# Set master PID and state locations<br />
pidfile "#{shared_dir}/pids/puma.pid"<br />
#state_path "#{shared_dir}/pids/puma.state"<br />
#activate_control_app<br />
<br />
#on_worker_boot do<br />
# require "active_record"<br />
# ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished<br />
# ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])<br />
#end</pre><br />
<br />
and start server with<br />
$ bundle exec puma -C config/puma.rb<br />
<br />
You can also run it in background with parameter {{ic|-d}} and check with<br />
$ ps aux| grep puma<br />
when you want to {{ic|kill}} it.<br />
<br />
==== Option 2: by systemd ====<br />
<br />
Create a new systemd unit {{ic|puma.service}} under /usr/lib/systemd/system/ and copy codes below<br />
<pre><br />
[Unit]<br />
Description=Puma application server<br />
After=network.target<br />
<br />
[Service]<br />
WorkingDirectory=/var/www/my_app<br />
#Environment=RAILS_ENV=production<br />
User=rails<br />
PIDFile=/var/www/my_app/shared/pids/puma.pid<br />
ExecStart=/home/rails/.gem/ruby/2.2.0/bin/bundle exec \<br />
/home/rails/.gem/ruby/2.2.0/bin/puma \<br />
-b unix:///var/www/my_app/shared/sockets/puma.sock \<br />
--pidfile /var/www/my_app/shared/pids/puma.pid<br />
<br />
[Install]<br />
WantedBy=multi-user.target</pre><br />
<br />
Then start puma with<br />
# systemctl start puma<br />
<br />
For further reading take a look at [[Ruby_on_Rails#References_2]]<br />
<br />
== Databases ==<br />
<br />
Most web applications will need to interact with some sort of database. ActiveRecord (the ORM used by Rails to provide database abstraction) supports several database vendors, the most popular of which are MySQL, SQLite, and PostgreSQL.<br />
<br />
=== SQLite ===<br />
<br />
SQLite is the default lightweight database for Ruby on Rails. To enable SQLite, simply install {{Pkg|sqlite}}.<br />
<br />
=== PostgreSQL ===<br />
<br />
Install {{Pkg|postgresql}}.<br />
<br />
=== MySQL ===<br />
<br />
First, install and configure a MySQL server. Please refer to [[MySQL]] on how to do this.<br />
<br />
A gem with some native extensions is required, probably best installed as root:<br />
# gem install mysql<br />
<br />
You can generate a rails application configured for MySQL by using the {{ic|-d}} parameter:<br />
$ rails new testapp_name -d mysql<br />
<br />
You then need to edit {{ic|config/database.yml}}. Rails uses different databases for development, testing, production and other environments. Here is an example development configuration for MySQL running on localhost:<br />
<br />
development:<br />
adapter: mysql<br />
database: my_application_database<br />
username: development<br />
password: my_secret_password<br />
<br />
Note that you do not have to actually create the database using MySQL, as this can be done via Rails with:<br />
# rake db:create<br />
<br />
If no errors are shown, then your database has been created and Rails can talk to your MySQL database.<br />
<br />
== The Perfect Rails Setup ==<br />
<br />
''Phusion Passenger running multiple Ruby versions.''<br />
<br />
* [https://www.archlinux.org/ Arch Linux]: A simple, lightweight distribution. ;)<br />
* [http://www.nginx.org/ Nginx]: A fast and lightweight '''web server''' with a strong focus on high concurrency, performance and low memory usage.<br />
* [http://www.modrails.com/ Passenger] (a.k.a. mod_rails or mod_rack): Supports both Apache and Nginx web servers. It makes deployment of Ruby web applications, such as those built on Ruby on Rails web framework, a breeze.<br />
* [https://rvm.io/ Ruby Version Manager] (RVM): A command-line tool which allows you to easily install, manage, and work with multiple Ruby environments from interpreters to sets of gems. RVM lets you deploy each project with its own completely self-contained and dedicated environment —from the specific version of ruby, all the way down to the precise set of required gems to run your application—.<br />
* [http://sqlite.org/ SQLite]: The default lightweight '''database''' for Ruby on Rails.<br />
<br />
=== Step 0: SQLite ===<br />
<br />
Install {{Pkg|sqlite}}.<br />
<br />
{{note|Of course SQLite is not critical in this setup, you can use MySQL and PostgreSQL as well.}}<br />
<br />
=== Step 1: RVM ===<br />
<br />
Make a multi-user [[RVM]] installation as specified [[RVM#Multi-user_installation|here]].<br />
<br />
In the 'adding users to the rvm group' step, do<br />
# usermod -a -G rvm http<br />
# usermod -a -G rvm nobody<br />
<br />
{{ic|http}} and {{ic|nobody}} are the users related to Nginx and Passenger, respectively.<br />
<br />
{{note|Maybe adding the 'nobody' user to the 'rvm' group is not necessary.}}<br />
<br />
=== Step 2: Rubies ===<br />
<br />
Once you have a working RVM installation in your hands, it is time to install the latest Ruby interpreter<br />
{{Note|During the installation of Ruby patches will be applied. Consider installing the {{ic|base-devel}} group beforehand.}}<br />
<br />
$ rvm install 2.0.0<br />
<br />
{{Note| It may be useful to delete the 'global' gemsets of the environments that have web applications. Their gems might somehow interfere with Passenger. In that case, a {{ic|rvm 2.0.0 do gemset delete global}} is sufficient.}}<br />
<br />
=== Step 3: Nginx with Passenger support ===<br />
<br />
Run the following to allow passenger install nginx:<br />
$ rvm use 2.0.0 <br />
$ gem install passenger<br />
$ rvmsudo passenger-install-nginx-module<br />
<br />
The passenger gem will be put into the ''default'' gemset.<br />
<br />
This will download the sources of Nginx, compile and install it for you. It will guide you through all the process. Note that the default location for Nginx will be {{ic|/opt/nginx}}.<br />
<br />
{{Note|If you encounter a compilation error regarding Boost threads, see [https://bbs.archlinux.org/viewtopic.php?id&#61;139164 this] article.}}<br />
<br />
After completion, add the following two lines into the 'http block' at {{ic|/opt/nginx/conf/nginx.conf}} that look like:<br />
<br />
http { <br />
...<br />
passenger_root /usr/local/rvm/gems/ruby-2.0.0-p353/gems/passenger-3.0.9;<br />
passenger_ruby /usr/local/rvm/wrappers/ruby-2.0.0-p353/ruby;<br />
...<br />
}<br />
<br />
{{Note|This step is currently being done automatically by the installer script.}}<br />
<br />
=== Step 4: Gemsets and Apps ===<br />
<br />
For each Rails application you should have a gemset. Suppose that you want to try [http://refinerycms.com RefineryCMS] against [http://www.browsercms.org BrowserCMS], two open-source Content Management Systems based on Rails.<br />
<br />
Install RefineryCMS first:<br />
<br />
$ rvm use 2.0.0@refinery --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install refinerycms refinerycms-i18n sqlite3<br />
<br />
Deploy a RefineryCMS instance called ''refineria'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo refinerycms refineria<br />
<br />
Install BrowserCMS in a different gemset:<br />
<br />
$ rvm use 2.0.0@browser --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install browsercms sqlite3<br />
<br />
Deploy a BrowserCMS instance called ''navegador'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo browsercms demo navegador<br />
$ cd /srv/http/navegador<br />
$ rvmsudo rake db:install<br />
<br />
=== Passenger for Nginx and Passenger Standalone ===<br />
<br />
Observe that the passenger gem was installed three times and with different intentions; in the environments<br />
* ''2.0.0'' => for Nginx,<br />
* ''2.0.0@refinery'' => Standalone<br />
* ''2.0.0@browser'' => Standalone<br />
<br />
The strategy is to combine Passenger for Nginx with Passenger Standalone. One must first identify the Ruby environment (interpreter plus gemset) that one uses the most; in this setup the Ruby interpreter and the default gemset were selected. One then proceeds with setting up Passenger for Nginx to use that environment (step 3).<br />
* Applications within the chosen environment can be served as in [[#Apache.2FNginx .28using Phusion Passenger.29|Apache/Nginx (using Phusion Passenger)]], page up in this article.<br />
* All applications that are to use a different Ruby version and/or gemset can be served separately through Passenger Standalone and hook into the main web server via a reverse proxy configuration (step 6).<br />
<br />
=== Step 5: .rvmrc files and ownerships ===<br />
<br />
This step is crucial for the correct behaviour of the setup. RVM seeks for .rvmrc files when changing folders; if it finds one, it reads it. In these files normally one stores a line like<br />
rvm <ruby_version>@<gemset_name><br />
so the specified environment is set at the entrance of applications' root folder.<br />
<br />
Create /srv/http/refineria/.rvmrc doing<br />
# echo "rvm ree@refinery" > /srv/http/refineria/.rvmrc<br />
, and /srv/http/navegador/.rvmrc with<br />
# echo "rvm 2.0.0@browser" > /srv/http/navegador/.rvmrc<br />
You have to enter to both application root folders now, because every first time that RVM finds a .rvmrc it asks you if you trust the given file, consequently you must validate the two files you have just created.<br />
<br />
These files aid the programs involved to find the correct gems.<br />
<br />
Apart, if applications' files and folders are not owned by the right user you will face database write-access problems. The use of rvmsudo produces ''root''-owned archives when generated by Rails; in the other hand, ''nobody'' is the user for Passenger —if you have not changed it—: who will use and should posses them. Fix this doing<br />
# chown -R nobody.nobody /srv/http/refineria /srv/http/navegador<br />
<br />
=== Step 6: Reverse proxies ===<br />
<br />
You have to start the Passenger Standalone web servers for your applications. So, do<br />
$ cd /srv/http/refineria<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
and<br />
$ cd /srv/http/navegador<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
. The first time that you run a Passenger Standalone it will perform a minor installation.<br />
<br />
Note that you are using ''unix domain'' sockets instead of the commonly-used ''TCP'' sockets; it turns out that unix domain are significantly faster than TCP sockets.<br />
<br />
{{note|If you are experimenting trouble with unix sockets, changing to TCP should work:<br />
rvmsudo passenger start -a 127.0.0.1 -p 3000 -d<br />
}}<br />
<br />
==== Launch Passenger Standalone daemons at system start-up ====<br />
<br />
''Do you have a script? Please post it here.''<br />
<br />
The systemd script below was made for a Typo blog I host at /srv/http/typo. It is located at /etc/systemd/system/passenger_typo.service. I set the Environment= tags (see "man systemd.exec") from the output of "rvm env". The only exception was PATH=, which I had to combine from my regular PATH and the output of rvm env.<br />
<br />
Note: If you do not set the "WorkingDirectory=" variable to your application folder, passenger will fail to find your app and will subsequently shut itself down.<br />
<br />
<pre><br />
[Unit]<br />
Description=Passenger Standalone Script for Typo<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
WorkingDirectory=/srv/http/typo<br />
PIDFile=/srv/http/typo/tmp/pids/passenger.pid<br />
<br />
Environment=PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo/bin:/usr/local/rvm/gems/ruby-2.0.0-p0@global/bin:/usr/local/rvm/rubies/ruby-2.0.0-p0/bin:/usr/local/rvm/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/bin/core_perl<br />
Environment=rvm_env_string=ruby-2.0.0-p0@typo<br />
Environment=rvm_path=/usr/local/rvm<br />
Environment=rvm_ruby_string=ruby-2.0.0-p0<br />
Environment=rvm_gemset_name=typo<br />
Environment=RUBY_VERSION=ruby-2.0.0-p0<br />
Environment=GEM_HOME=/usr/local/rvm/gems/ruby-2.0.0-p0@typo<br />
Environment=GEM_PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo:/usr/local/rvm/gems/ruby-2.0.0-p0@global<br />
Environment=MY_RUBY_HOME=/usr/local/rvm/rubies/ruby-2.0.0-p0<br />
Environment=IRBRC=/usr/local/rvm/rubies/ruby-2.0.0-p0/.irbrc<br />
<br />
ExecStart=/bin/bash -c "rvmsudo passenger start --socket /srv/http/typo/tmp/sockets/passenger.socket -d"<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
</pre><br />
<br />
=== Step 7: Deployment ===<br />
<br />
==== With subdomains ====<br />
<br />
Once again edit /opt/nginx/conf/nginx.conf to include some vital instructions:<br />
<br />
<pre><br />
## RefineryCMS ##<br />
<br />
server {<br />
server_name refinery.domain.com;<br />
root /srv/http/refineria/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/refineria/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
<br />
## BrowserCMS ##<br />
<br />
server {<br />
server_name browser.domain.com;<br />
root /srv/http/navegador/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/navegador/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
{{note|Or if using TCP sockets, configure the ''proxy_pass'' directive like<br />
<pre>proxy_pass http://127.0.0.1:3000;</pre><br />
}}<br />
<br />
==== Without subdomains ====<br />
<br />
If you for some reason do not want to host each application on its own subdomain but rather in a url like: {{ic|site.com/railsapp}} then you could do something like this in your config:<br />
<br />
<pre><br />
server {<br />
server_name site.com;<br />
#Base for the html files etc<br />
root /srv/http/;<br />
<br />
#First application you want hosted under domain site.com/railsapp<br />
location /railsapp {<br />
root /srv/http/railsapp/public;<br />
#you may need to change passenger_base_uri to be the uri you want to point at, ie:<br />
#passenger_base_uri /railsapp;<br />
#but probably only if you are using the other solution with passenger phusion<br />
proxy_pass http://unix:/srv/http/railsapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
<br />
#Second applicatino you want hosted under domain site.com/anotherapp<br />
location /anotherapp {<br />
root /srv/http/anotherapp/public;<br />
#same thing about the passenger_base_uri here, but with value /anotherapp instead<br />
proxy_pass http://unix:/srv/http/anotherapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
At this point you are in conditions to run Nginx with:<br />
<br />
# systemctl start nginx<br />
<br />
and to access both CMSs through ''refinery.domain.com'' and ''browser.domain.com''.<br />
<br />
=== References ===<br />
<br />
* http://beginrescueend.com/integration/passenger<br />
* http://blog.phusion.nl/2010/09/21/phusion-passenger-running-multiple-ruby-versions<br />
* http://www.ruby-journal.com/how-to-setup-rails-app-with-puma-and-nginx/<br />
* https://www.digitalocean.com/community/tutorials/how-to-deploy-a-rails-app-with-puma-and-nginx-on-ubuntu-14-04<br />
<br />
== See also ==<br />
<br />
* [[Ruby]]<br />
* [[Nginx]]<br />
* [[LAMP]]<br />
* [[MySQL]]<br />
<br />
== References ==<br />
<br />
* Ruby on Rails http://rubyonrails.org/download.<br />
* Mongrel http://mongrel.rubyforge.org.</div>Stbinanhttps://wiki.archlinux.org/index.php?title=Ruby_on_Rails&diff=391494Ruby on Rails2015-08-17T09:34:54Z<p>Stbinan: /* Puma (with Nginx as reverse proxy server) */</p>
<hr />
<div>[[Category:Web server]]<br />
[[zh-CN:Ruby on Rails]]<br />
[http://rubyonrails.org/ Ruby on Rails], often shortened to Rails or RoR, is an open source web application framework for the Ruby programming language. It is intended to be used with an Agile development methodology that is used by web developers for rapid development.<br />
<br />
This document describes how to set up the Ruby on Rails Framework on an Arch Linux system.<br />
<br />
== Installation ==<br />
<br />
Ruby on Rails requires [[Ruby]] to be installed, so read that article first for installation instructions. The {{pkg|nodejs}} package is also required.<br />
<br />
Ruby on Rails itself can be installed multiple ways:<br />
<br />
=== Option A: via RubyGems ===<br />
<br />
{{Note|You can also install Rails system-wide using Gems. To do this, run the following commands as root and append them with {{ic|--no-user-install}}. Please read [[Ruby#Installing gems per-user or system-wide]] for possible dangers of using RubyGem in this way.}}<br />
<br />
The following command will install Rails for the current user:<br />
$ gem install rails<br />
<br />
Building the documentation takes a while. If you want to skip it, append {{ic|--no-document}} to the install command.<br />
$ gem install rails --no-document<br />
<br />
gem is a package manager for Ruby modules, somewhat like pacman is to Arch Linux. To update your gems, simply run:<br />
$ gem update<br />
<br />
=== Option B: via pacgem ===<br />
<br />
You can install Rails using {{AUR|pacgem}} from the [[AUR]]. Pacgem automatically creates PKGBUILDs and Arch packages for each of the gems. These packages will then be installed using pacman.<br />
# pacgem rails<br />
<br />
The gem packages can be updated with<br />
# pacgem -u<br />
<br />
=== Option C: from the AUR ===<br />
<br />
{{Warning|This is not recommended, as this might not include the latest Rails version, and additional dependencies may be introduced that may require you to run {{Ic|gem install}} anyway.}}<br />
<br />
There is a {{AUR|ruby-rails}} package available in the [[AUR]].<br />
<br />
=== Option D: from Quarry binary repository ===<br />
<br />
[[pacman|Install]] ''ruby-rails'' from the unofficial [[Unofficial user repositories#quarry|quarry]] repository.<br />
<br />
== Configuration ==<br />
<br />
Rails is bundled with a basic HTTP server called WeBrick. You can create a test application to test it. First, create an application with the rails command:<br />
<br />
$ rails new testapp_name<br />
<br />
{{Note|If you get an error like {{ic|Errno::ENOENT: No such file or directory (...) An error occurred while installing x, and Bundler cannot continue.}}, you might have to configure [[Ruby#Bundler|Bundler]] so that it installs gems per-user and not system-wide. Alternatively, run {{ic|# rails new testapp_name}} once as root. If it has completed successfully, delete {{ic|testapp_name/}} and run {{ic|$ rails new testapp_name}} again as a regular user.}}<br />
{{Note|If you get an error message like this:<br />
{{ic|... FetchError: SSL_connect returned&#61;1 errno&#61; 0 state&#61;SSLv2/v3 read server hello A: sslv3 alert handshake<br />
failure <nowiki>(https://s3.amazonaws.com/ production.s3.rubygems.org/gems/rake-10.0.3.gem)</nowiki> }}<br />
install {{Pkg|nodejs}} and try again.}}<br />
<br />
This creates a new folder inside your current working directory. <br />
<br />
$ cd testapp_name<br />
<br />
Next start the web server. It listens on port 3000 by default:<br />
<br />
$ rails server<br />
<br />
Now visit the testapp_name website on your local machine by opening <nowiki>http://localhost:3000</nowiki> in your browser<br />
{{Note|If Ruby complains about not being able to find a JavaScript runtime, install {{Pkg|nodejs}}.}}<br />
<br />
A test-page should shown greeting you "Welcome aboard".<br />
<br />
== Application servers ==<br />
<br />
The built-in Ruby On Rails HTTP server (WeBrick) is convenient for basic development, but it is not recommended for production use. Instead, you should use an application server such as [[#Thin]], [[#Unicorn]] or [[#Apache/Nginx (using Phusion Passenger)|Phusion Passenger]].<br />
<br />
=== Thin ===<br />
<br />
[http://code.macournoyer.com/thin/ Thin] is a fast and very simple Ruby web server.<br />
<br />
First install thin gem:<br />
$ gem install thin<br />
<br />
Then start it using:<br />
$ thin start<br />
<br />
=== Unicorn ===<br />
<br />
Unicorn is an application server that cannot talk directly to clients. Instead, a web server must sit between clients and Unicorn, proxying requests as needed. [http://unicorn.bogomips.org/ Unicorn] is loosely based on Mongrel. It is used by Github, and it uses an architecture that tries hard to find the best child for handling a request. [https://github.com/blog/517-unicorn Explanation of differences between Unicorn and Mongrel].<br />
<br />
Install the Unicorn gem:<br />
# gem install unicorn<br />
<br />
Then create a configuration file for your application in {{ic|/etc/unicorn/}}. For example; here is a configuration example (Based on [http://www.warden.pl/2011/01/07/running-redmine-under-unicorn-in-debian/]) for Redmine:<br />
<br />
{{hc|/etc/unicorn/redmine.ru|<nowiki><br />
working_directory "/srv/http/redmine"<br />
pid "/tmp/redmine.pid"<br />
<br />
preload_app true<br />
timeout 60<br />
worker_processes 4<br />
listen 4000<br />
stderr_path('/var/log/unicorn.log')<br />
<br />
GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true<br />
<br />
after_fork do |server, worker|<br />
#start the worker on port 4000, 4001, 4002 etc...<br />
addr = "0.0.0.0:#{4000 + worker.nr}"<br />
# infinite tries to start the worker<br />
server.listen(addr, :tries => -1, :delay => -1, :backlog => 128)<br />
<br />
#Drop privileges if running as root<br />
worker.user('nobody', 'nobody') if Process.euid == 0<br />
end<br />
</nowiki>}}<br />
<br />
Start it using:<br />
# /usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
==== Systemd service ====<br />
<br />
Put the following contents in {{ic|/etc/systemd/system/unicorn.service}}:<br />
{{hc|/etc/systemd/system/unicorn.service|2=<br />
[Unit]<br />
Description=Unicorn application server<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
User=redmine<br />
ExecStart=/usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
}}<br />
<br />
You can now easily start and stop unicorn using systemctl<br />
<br />
==== Nginx Configuration ====<br />
<br />
After setting up [[Nginx]], configure unicorn as an upstream server using something like this (Warning: this is a stripped example. It probably does not work without additional configuration):<br />
{{bc|1=<br />
http {<br />
upstream unicorn {<br />
server 127.0.0.1:4000 fail_timeout=0;<br />
server 127.0.0.1:4001 fail_timeout=0;<br />
server 127.0.0.1:4002 fail_timeout=0;<br />
server 127.0.0.1:4003 fail_timeout=0;<br />
}<br />
<br />
server {<br />
listen 80 default;<br />
server_name YOURHOSTNAMEHERE;<br />
<br />
location / {<br />
root /srv/http/redmine/public;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
proxy_pass http://unicorn;<br />
}<br />
}<br />
}<br />
}}<br />
<br />
=== Apache/Nginx (using Phusion Passenger) ===<br />
<br />
[http://www.modrails.com/ Passenger] also known as {{ic|mod_rails}} is a module available for [[Nginx]] and [[Apache]], that greatly simplifies setting up a Rails server environment. Nginx does not support modules as Apache and has to be compiled with {{ic|mod_rails}} in order to support Passenger; let Passenger compile it for you. As for Apache, let Passenger set up the module for you.<br />
<br />
Start by installing the 'passenger' gem:<br />
# gem install passenger<br />
<br />
If you are aiming to use [[Apache]], run:<br />
# passenger-install-apache2-module<br />
<br />
In case a rails application is deployed with a sub-URI, like http://example.com/yourapplication, some additional configuration is required, see [http://www.modrails.com/documentation/Users%20guide%20Apache.html#deploying_rails_to_sub_uri the modrails documentation]<br />
<br />
For [[Nginx]]:<br />
# passenger-install-nginx-module<br />
<br />
The installer will provide you with any additional information regarding the installation (such as installing additional libraries).<br />
<br />
To serve an application with Nginx, configure it as follows:<br />
<pre><br />
server {<br />
server_name app.example.org;<br />
root path_to_app/public; # Be sure to point to 'public' folder!<br />
passenger_enabled on;<br />
rails_env development; # Rails environment.<br />
}<br />
</pre><br />
<br />
=== Puma (with Nginx as reverse proxy server) ===<br />
<br />
[http://puma.io/ Puma] ([https://github.com/puma/puma Github Page]) is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications, and is considered the replacement for Webrick and Mongrel. It was designed to be the go-to server for Rubinius, but also works well with JRuby and MRI. While reverse proxy server would acts as a load balancer that routes all external requests to a pool of web apps.<br />
<br />
For a webserver it is better to use a server user and group, check [[Users_and_groups#Example_adding_a_user]], below use {{ic|rails}} as user name and {{ic|server}} as group name, also {{ic|my_app}} as rails app name.<br />
<br />
Start by copying your app to /var/www/my_app. And set new ownership with<br />
# cd /var/www/<br />
# chown -R rails:server my_app<br />
<br />
and permission for user with<br />
# chmod -R 775 my_app<br />
<br />
Then add puma gem in the Gemfile and install with<br />
$ cd my_app <br />
$ bundle install<br />
<br />
Also install {{ic|nginx}} by pacman.<br />
<br />
Under your app folder, create sockets, pid and log folder with<br />
$ mkdir -p shared/pids shared/sockets shared/log<br />
<br />
Backup nginx.conf with<br />
# cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup<br />
<br />
Then create a new nginx.conf file with your favorite editor, copy codes below and modify as you like:<br />
<pre><br />
#user html;<br />
worker_processes 1; # this may connect with the worker numbers puma can use.<br />
<br />
#error_log logs/error.log;<br />
#error_log logs/error.log notice;<br />
#error_log logs/error.log info;<br />
<br />
#pid logs/nginx.pid;<br />
<br />
<br />
events {<br />
worker_connections 1024;<br />
}<br />
<br />
http {<br />
upstream app {<br />
# Path to Puma SOCK file, as defined previously<br />
server unix:/var/www/my_app/shared/sockets/puma.sock;<br />
}<br />
<br />
server {<br />
listen 80;<br />
server_name localhost; # or your server name<br />
<br />
root /var/www/my_app/public;<br />
<br />
try_files $uri/index.html $uri @app;<br />
<br />
location @app {<br />
proxy_pass http://app;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
}<br />
<br />
error_page 500 502 503 504 /500.html;<br />
client_max_body_size 4G;<br />
keepalive_timeout 10;<br />
}<br />
}</pre><br />
<br />
Start nginx service with<br />
# systemctl start nginx<br />
<br />
<br />
There are several ways to start puma server, two ways are recommended below:<br />
<br />
==== Option A: With config file ====<br />
<br />
Create file {{ic|config/puma.rb}}, copy codes below and modify as you like:<br />
<pre><br />
# Change to match your CPU core count<br />
# You can check available worker numbers with $ grep -c processor /proc/cpuinfo<br />
# also see the comment in the nginx.conf<br />
workers 2<br />
<br />
# Min and Max threads per worker<br />
#threads 1, 6<br />
<br />
app_dir = File.expand_path("../..", __FILE__)<br />
shared_dir = "#{app_dir}/shared"<br />
<br />
# Default to production<br />
#rails_env = ENV['RAILS_ENV'] || "production"<br />
#environment rails_env<br />
<br />
# Set up socket location<br />
bind "unix://#{shared_dir}/sockets/puma.sock"<br />
<br />
# Logging<br />
#stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true<br />
<br />
# Set master PID and state locations<br />
pidfile "#{shared_dir}/pids/puma.pid"<br />
#state_path "#{shared_dir}/pids/puma.state"<br />
#activate_control_app<br />
<br />
#on_worker_boot do<br />
# require "active_record"<br />
# ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished<br />
# ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])<br />
#end</pre><br />
<br />
and start server with<br />
$ bundle exec puma -C config/puma.rb<br />
<br />
You can also run it in background with parameter {{ic|-d}} and check with<br />
$ ps aux| grep puma<br />
when you want to {{ic|kill}} it.<br />
<br />
==== Option 2: by systemd ====<br />
<br />
Create a new systemd unit {{ic|puma.service}} under /usr/lib/systemd/system/ and copy codes below<br />
<pre><br />
[Unit]<br />
Description=Puma application server<br />
After=network.target<br />
<br />
[Service]<br />
WorkingDirectory=/var/www/my_app<br />
#Environment=RAILS_ENV=production<br />
User=rails<br />
PIDFile=/var/www/my_app/shared/pids/puma.pid<br />
ExecStart=/home/rails/.gem/ruby/2.2.0/bin/bundle exec \<br />
/home/rails/.gem/ruby/2.2.0/bin/puma \<br />
-b unix:///var/www/my_app/shared/sockets/puma.sock \<br />
--pidfile /var/www/my_app/shared/pids/puma.pid<br />
<br />
[Install]<br />
WantedBy=multi-user.target</pre><br />
<br />
Then start puma with<br />
# systemctl start puma<br />
<br />
For further reading take a look at [[Ruby_on_Rails#References_2]]<br />
<br />
== Databases ==<br />
<br />
Most web applications will need to interact with some sort of database. ActiveRecord (the ORM used by Rails to provide database abstraction) supports several database vendors, the most popular of which are MySQL, SQLite, and PostgreSQL.<br />
<br />
=== SQLite ===<br />
<br />
SQLite is the default lightweight database for Ruby on Rails. To enable SQLite, simply install {{Pkg|sqlite}}.<br />
<br />
=== PostgreSQL ===<br />
<br />
Install {{Pkg|postgresql}}.<br />
<br />
=== MySQL ===<br />
<br />
First, install and configure a MySQL server. Please refer to [[MySQL]] on how to do this.<br />
<br />
A gem with some native extensions is required, probably best installed as root:<br />
# gem install mysql<br />
<br />
You can generate a rails application configured for MySQL by using the {{ic|-d}} parameter:<br />
$ rails new testapp_name -d mysql<br />
<br />
You then need to edit {{ic|config/database.yml}}. Rails uses different databases for development, testing, production and other environments. Here is an example development configuration for MySQL running on localhost:<br />
<br />
development:<br />
adapter: mysql<br />
database: my_application_database<br />
username: development<br />
password: my_secret_password<br />
<br />
Note that you do not have to actually create the database using MySQL, as this can be done via Rails with:<br />
# rake db:create<br />
<br />
If no errors are shown, then your database has been created and Rails can talk to your MySQL database.<br />
<br />
== The Perfect Rails Setup ==<br />
<br />
''Phusion Passenger running multiple Ruby versions.''<br />
<br />
* [https://www.archlinux.org/ Arch Linux]: A simple, lightweight distribution. ;)<br />
* [http://www.nginx.org/ Nginx]: A fast and lightweight '''web server''' with a strong focus on high concurrency, performance and low memory usage.<br />
* [http://www.modrails.com/ Passenger] (a.k.a. mod_rails or mod_rack): Supports both Apache and Nginx web servers. It makes deployment of Ruby web applications, such as those built on Ruby on Rails web framework, a breeze.<br />
* [https://rvm.io/ Ruby Version Manager] (RVM): A command-line tool which allows you to easily install, manage, and work with multiple Ruby environments from interpreters to sets of gems. RVM lets you deploy each project with its own completely self-contained and dedicated environment —from the specific version of ruby, all the way down to the precise set of required gems to run your application—.<br />
* [http://sqlite.org/ SQLite]: The default lightweight '''database''' for Ruby on Rails.<br />
<br />
=== Step 0: SQLite ===<br />
<br />
Install {{Pkg|sqlite}}.<br />
<br />
{{note|Of course SQLite is not critical in this setup, you can use MySQL and PostgreSQL as well.}}<br />
<br />
=== Step 1: RVM ===<br />
<br />
Make a multi-user [[RVM]] installation as specified [[RVM#Multi-user_installation|here]].<br />
<br />
In the 'adding users to the rvm group' step, do<br />
# usermod -a -G rvm http<br />
# usermod -a -G rvm nobody<br />
<br />
{{ic|http}} and {{ic|nobody}} are the users related to Nginx and Passenger, respectively.<br />
<br />
{{note|Maybe adding the 'nobody' user to the 'rvm' group is not necessary.}}<br />
<br />
=== Step 2: Rubies ===<br />
<br />
Once you have a working RVM installation in your hands, it is time to install the latest Ruby interpreter<br />
{{Note|During the installation of Ruby patches will be applied. Consider installing the {{ic|base-devel}} group beforehand.}}<br />
<br />
$ rvm install 2.0.0<br />
<br />
{{Note| It may be useful to delete the 'global' gemsets of the environments that have web applications. Their gems might somehow interfere with Passenger. In that case, a {{ic|rvm 2.0.0 do gemset delete global}} is sufficient.}}<br />
<br />
=== Step 3: Nginx with Passenger support ===<br />
<br />
Run the following to allow passenger install nginx:<br />
$ rvm use 2.0.0 <br />
$ gem install passenger<br />
$ rvmsudo passenger-install-nginx-module<br />
<br />
The passenger gem will be put into the ''default'' gemset.<br />
<br />
This will download the sources of Nginx, compile and install it for you. It will guide you through all the process. Note that the default location for Nginx will be {{ic|/opt/nginx}}.<br />
<br />
{{Note|If you encounter a compilation error regarding Boost threads, see [https://bbs.archlinux.org/viewtopic.php?id&#61;139164 this] article.}}<br />
<br />
After completion, add the following two lines into the 'http block' at {{ic|/opt/nginx/conf/nginx.conf}} that look like:<br />
<br />
http { <br />
...<br />
passenger_root /usr/local/rvm/gems/ruby-2.0.0-p353/gems/passenger-3.0.9;<br />
passenger_ruby /usr/local/rvm/wrappers/ruby-2.0.0-p353/ruby;<br />
...<br />
}<br />
<br />
{{Note|This step is currently being done automatically by the installer script.}}<br />
<br />
=== Step 4: Gemsets and Apps ===<br />
<br />
For each Rails application you should have a gemset. Suppose that you want to try [http://refinerycms.com RefineryCMS] against [http://www.browsercms.org BrowserCMS], two open-source Content Management Systems based on Rails.<br />
<br />
Install RefineryCMS first:<br />
<br />
$ rvm use 2.0.0@refinery --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install refinerycms refinerycms-i18n sqlite3<br />
<br />
Deploy a RefineryCMS instance called ''refineria'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo refinerycms refineria<br />
<br />
Install BrowserCMS in a different gemset:<br />
<br />
$ rvm use 2.0.0@browser --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install browsercms sqlite3<br />
<br />
Deploy a BrowserCMS instance called ''navegador'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo browsercms demo navegador<br />
$ cd /srv/http/navegador<br />
$ rvmsudo rake db:install<br />
<br />
=== Passenger for Nginx and Passenger Standalone ===<br />
<br />
Observe that the passenger gem was installed three times and with different intentions; in the environments<br />
* ''2.0.0'' => for Nginx,<br />
* ''2.0.0@refinery'' => Standalone<br />
* ''2.0.0@browser'' => Standalone<br />
<br />
The strategy is to combine Passenger for Nginx with Passenger Standalone. One must first identify the Ruby environment (interpreter plus gemset) that one uses the most; in this setup the Ruby interpreter and the default gemset were selected. One then proceeds with setting up Passenger for Nginx to use that environment (step 3).<br />
* Applications within the chosen environment can be served as in [[#Apache.2FNginx .28using Phusion Passenger.29|Apache/Nginx (using Phusion Passenger)]], page up in this article.<br />
* All applications that are to use a different Ruby version and/or gemset can be served separately through Passenger Standalone and hook into the main web server via a reverse proxy configuration (step 6).<br />
<br />
=== Step 5: .rvmrc files and ownerships ===<br />
<br />
This step is crucial for the correct behaviour of the setup. RVM seeks for .rvmrc files when changing folders; if it finds one, it reads it. In these files normally one stores a line like<br />
rvm <ruby_version>@<gemset_name><br />
so the specified environment is set at the entrance of applications' root folder.<br />
<br />
Create /srv/http/refineria/.rvmrc doing<br />
# echo "rvm ree@refinery" > /srv/http/refineria/.rvmrc<br />
, and /srv/http/navegador/.rvmrc with<br />
# echo "rvm 2.0.0@browser" > /srv/http/navegador/.rvmrc<br />
You have to enter to both application root folders now, because every first time that RVM finds a .rvmrc it asks you if you trust the given file, consequently you must validate the two files you have just created.<br />
<br />
These files aid the programs involved to find the correct gems.<br />
<br />
Apart, if applications' files and folders are not owned by the right user you will face database write-access problems. The use of rvmsudo produces ''root''-owned archives when generated by Rails; in the other hand, ''nobody'' is the user for Passenger —if you have not changed it—: who will use and should posses them. Fix this doing<br />
# chown -R nobody.nobody /srv/http/refineria /srv/http/navegador<br />
<br />
=== Step 6: Reverse proxies ===<br />
<br />
You have to start the Passenger Standalone web servers for your applications. So, do<br />
$ cd /srv/http/refineria<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
and<br />
$ cd /srv/http/navegador<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
. The first time that you run a Passenger Standalone it will perform a minor installation.<br />
<br />
Note that you are using ''unix domain'' sockets instead of the commonly-used ''TCP'' sockets; it turns out that unix domain are significantly faster than TCP sockets.<br />
<br />
{{note|If you are experimenting trouble with unix sockets, changing to TCP should work:<br />
rvmsudo passenger start -a 127.0.0.1 -p 3000 -d<br />
}}<br />
<br />
==== Launch Passenger Standalone daemons at system start-up ====<br />
<br />
''Do you have a script? Please post it here.''<br />
<br />
The systemd script below was made for a Typo blog I host at /srv/http/typo. It is located at /etc/systemd/system/passenger_typo.service. I set the Environment= tags (see "man systemd.exec") from the output of "rvm env". The only exception was PATH=, which I had to combine from my regular PATH and the output of rvm env.<br />
<br />
Note: If you do not set the "WorkingDirectory=" variable to your application folder, passenger will fail to find your app and will subsequently shut itself down.<br />
<br />
<pre><br />
[Unit]<br />
Description=Passenger Standalone Script for Typo<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
WorkingDirectory=/srv/http/typo<br />
PIDFile=/srv/http/typo/tmp/pids/passenger.pid<br />
<br />
Environment=PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo/bin:/usr/local/rvm/gems/ruby-2.0.0-p0@global/bin:/usr/local/rvm/rubies/ruby-2.0.0-p0/bin:/usr/local/rvm/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/bin/core_perl<br />
Environment=rvm_env_string=ruby-2.0.0-p0@typo<br />
Environment=rvm_path=/usr/local/rvm<br />
Environment=rvm_ruby_string=ruby-2.0.0-p0<br />
Environment=rvm_gemset_name=typo<br />
Environment=RUBY_VERSION=ruby-2.0.0-p0<br />
Environment=GEM_HOME=/usr/local/rvm/gems/ruby-2.0.0-p0@typo<br />
Environment=GEM_PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo:/usr/local/rvm/gems/ruby-2.0.0-p0@global<br />
Environment=MY_RUBY_HOME=/usr/local/rvm/rubies/ruby-2.0.0-p0<br />
Environment=IRBRC=/usr/local/rvm/rubies/ruby-2.0.0-p0/.irbrc<br />
<br />
ExecStart=/bin/bash -c "rvmsudo passenger start --socket /srv/http/typo/tmp/sockets/passenger.socket -d"<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
</pre><br />
<br />
=== Step 7: Deployment ===<br />
<br />
==== With subdomains ====<br />
<br />
Once again edit /opt/nginx/conf/nginx.conf to include some vital instructions:<br />
<br />
<pre><br />
## RefineryCMS ##<br />
<br />
server {<br />
server_name refinery.domain.com;<br />
root /srv/http/refineria/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/refineria/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
<br />
## BrowserCMS ##<br />
<br />
server {<br />
server_name browser.domain.com;<br />
root /srv/http/navegador/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/navegador/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
{{note|Or if using TCP sockets, configure the ''proxy_pass'' directive like<br />
<pre>proxy_pass http://127.0.0.1:3000;</pre><br />
}}<br />
<br />
==== Without subdomains ====<br />
<br />
If you for some reason do not want to host each application on its own subdomain but rather in a url like: {{ic|site.com/railsapp}} then you could do something like this in your config:<br />
<br />
<pre><br />
server {<br />
server_name site.com;<br />
#Base for the html files etc<br />
root /srv/http/;<br />
<br />
#First application you want hosted under domain site.com/railsapp<br />
location /railsapp {<br />
root /srv/http/railsapp/public;<br />
#you may need to change passenger_base_uri to be the uri you want to point at, ie:<br />
#passenger_base_uri /railsapp;<br />
#but probably only if you are using the other solution with passenger phusion<br />
proxy_pass http://unix:/srv/http/railsapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
<br />
#Second applicatino you want hosted under domain site.com/anotherapp<br />
location /anotherapp {<br />
root /srv/http/anotherapp/public;<br />
#same thing about the passenger_base_uri here, but with value /anotherapp instead<br />
proxy_pass http://unix:/srv/http/anotherapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
At this point you are in conditions to run Nginx with:<br />
<br />
# systemctl start nginx<br />
<br />
and to access both CMSs through ''refinery.domain.com'' and ''browser.domain.com''.<br />
<br />
=== References ===<br />
<br />
* http://beginrescueend.com/integration/passenger<br />
* http://blog.phusion.nl/2010/09/21/phusion-passenger-running-multiple-ruby-versions<br />
<br />
== See also ==<br />
<br />
* [[Ruby]]<br />
* [[Nginx]]<br />
* [[LAMP]]<br />
* [[MySQL]]<br />
<br />
== References ==<br />
<br />
* Ruby on Rails http://rubyonrails.org/download.<br />
* Mongrel http://mongrel.rubyforge.org.</div>Stbinanhttps://wiki.archlinux.org/index.php?title=Ruby_on_Rails&diff=391493Ruby on Rails2015-08-17T09:31:09Z<p>Stbinan: /* Application servers */</p>
<hr />
<div>[[Category:Web server]]<br />
[[zh-CN:Ruby on Rails]]<br />
[http://rubyonrails.org/ Ruby on Rails], often shortened to Rails or RoR, is an open source web application framework for the Ruby programming language. It is intended to be used with an Agile development methodology that is used by web developers for rapid development.<br />
<br />
This document describes how to set up the Ruby on Rails Framework on an Arch Linux system.<br />
<br />
== Installation ==<br />
<br />
Ruby on Rails requires [[Ruby]] to be installed, so read that article first for installation instructions. The {{pkg|nodejs}} package is also required.<br />
<br />
Ruby on Rails itself can be installed multiple ways:<br />
<br />
=== Option A: via RubyGems ===<br />
<br />
{{Note|You can also install Rails system-wide using Gems. To do this, run the following commands as root and append them with {{ic|--no-user-install}}. Please read [[Ruby#Installing gems per-user or system-wide]] for possible dangers of using RubyGem in this way.}}<br />
<br />
The following command will install Rails for the current user:<br />
$ gem install rails<br />
<br />
Building the documentation takes a while. If you want to skip it, append {{ic|--no-document}} to the install command.<br />
$ gem install rails --no-document<br />
<br />
gem is a package manager for Ruby modules, somewhat like pacman is to Arch Linux. To update your gems, simply run:<br />
$ gem update<br />
<br />
=== Option B: via pacgem ===<br />
<br />
You can install Rails using {{AUR|pacgem}} from the [[AUR]]. Pacgem automatically creates PKGBUILDs and Arch packages for each of the gems. These packages will then be installed using pacman.<br />
# pacgem rails<br />
<br />
The gem packages can be updated with<br />
# pacgem -u<br />
<br />
=== Option C: from the AUR ===<br />
<br />
{{Warning|This is not recommended, as this might not include the latest Rails version, and additional dependencies may be introduced that may require you to run {{Ic|gem install}} anyway.}}<br />
<br />
There is a {{AUR|ruby-rails}} package available in the [[AUR]].<br />
<br />
=== Option D: from Quarry binary repository ===<br />
<br />
[[pacman|Install]] ''ruby-rails'' from the unofficial [[Unofficial user repositories#quarry|quarry]] repository.<br />
<br />
== Configuration ==<br />
<br />
Rails is bundled with a basic HTTP server called WeBrick. You can create a test application to test it. First, create an application with the rails command:<br />
<br />
$ rails new testapp_name<br />
<br />
{{Note|If you get an error like {{ic|Errno::ENOENT: No such file or directory (...) An error occurred while installing x, and Bundler cannot continue.}}, you might have to configure [[Ruby#Bundler|Bundler]] so that it installs gems per-user and not system-wide. Alternatively, run {{ic|# rails new testapp_name}} once as root. If it has completed successfully, delete {{ic|testapp_name/}} and run {{ic|$ rails new testapp_name}} again as a regular user.}}<br />
{{Note|If you get an error message like this:<br />
{{ic|... FetchError: SSL_connect returned&#61;1 errno&#61; 0 state&#61;SSLv2/v3 read server hello A: sslv3 alert handshake<br />
failure <nowiki>(https://s3.amazonaws.com/ production.s3.rubygems.org/gems/rake-10.0.3.gem)</nowiki> }}<br />
install {{Pkg|nodejs}} and try again.}}<br />
<br />
This creates a new folder inside your current working directory. <br />
<br />
$ cd testapp_name<br />
<br />
Next start the web server. It listens on port 3000 by default:<br />
<br />
$ rails server<br />
<br />
Now visit the testapp_name website on your local machine by opening <nowiki>http://localhost:3000</nowiki> in your browser<br />
{{Note|If Ruby complains about not being able to find a JavaScript runtime, install {{Pkg|nodejs}}.}}<br />
<br />
A test-page should shown greeting you "Welcome aboard".<br />
<br />
== Application servers ==<br />
<br />
The built-in Ruby On Rails HTTP server (WeBrick) is convenient for basic development, but it is not recommended for production use. Instead, you should use an application server such as [[#Thin]], [[#Unicorn]] or [[#Apache/Nginx (using Phusion Passenger)|Phusion Passenger]].<br />
<br />
=== Thin ===<br />
<br />
[http://code.macournoyer.com/thin/ Thin] is a fast and very simple Ruby web server.<br />
<br />
First install thin gem:<br />
$ gem install thin<br />
<br />
Then start it using:<br />
$ thin start<br />
<br />
=== Unicorn ===<br />
<br />
Unicorn is an application server that cannot talk directly to clients. Instead, a web server must sit between clients and Unicorn, proxying requests as needed. [http://unicorn.bogomips.org/ Unicorn] is loosely based on Mongrel. It is used by Github, and it uses an architecture that tries hard to find the best child for handling a request. [https://github.com/blog/517-unicorn Explanation of differences between Unicorn and Mongrel].<br />
<br />
Install the Unicorn gem:<br />
# gem install unicorn<br />
<br />
Then create a configuration file for your application in {{ic|/etc/unicorn/}}. For example; here is a configuration example (Based on [http://www.warden.pl/2011/01/07/running-redmine-under-unicorn-in-debian/]) for Redmine:<br />
<br />
{{hc|/etc/unicorn/redmine.ru|<nowiki><br />
working_directory "/srv/http/redmine"<br />
pid "/tmp/redmine.pid"<br />
<br />
preload_app true<br />
timeout 60<br />
worker_processes 4<br />
listen 4000<br />
stderr_path('/var/log/unicorn.log')<br />
<br />
GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true<br />
<br />
after_fork do |server, worker|<br />
#start the worker on port 4000, 4001, 4002 etc...<br />
addr = "0.0.0.0:#{4000 + worker.nr}"<br />
# infinite tries to start the worker<br />
server.listen(addr, :tries => -1, :delay => -1, :backlog => 128)<br />
<br />
#Drop privileges if running as root<br />
worker.user('nobody', 'nobody') if Process.euid == 0<br />
end<br />
</nowiki>}}<br />
<br />
Start it using:<br />
# /usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
==== Systemd service ====<br />
<br />
Put the following contents in {{ic|/etc/systemd/system/unicorn.service}}:<br />
{{hc|/etc/systemd/system/unicorn.service|2=<br />
[Unit]<br />
Description=Unicorn application server<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
User=redmine<br />
ExecStart=/usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
}}<br />
<br />
You can now easily start and stop unicorn using systemctl<br />
<br />
==== Nginx Configuration ====<br />
<br />
After setting up [[Nginx]], configure unicorn as an upstream server using something like this (Warning: this is a stripped example. It probably does not work without additional configuration):<br />
{{bc|1=<br />
http {<br />
upstream unicorn {<br />
server 127.0.0.1:4000 fail_timeout=0;<br />
server 127.0.0.1:4001 fail_timeout=0;<br />
server 127.0.0.1:4002 fail_timeout=0;<br />
server 127.0.0.1:4003 fail_timeout=0;<br />
}<br />
<br />
server {<br />
listen 80 default;<br />
server_name YOURHOSTNAMEHERE;<br />
<br />
location / {<br />
root /srv/http/redmine/public;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
proxy_pass http://unicorn;<br />
}<br />
}<br />
}<br />
}}<br />
<br />
=== Apache/Nginx (using Phusion Passenger) ===<br />
<br />
[http://www.modrails.com/ Passenger] also known as {{ic|mod_rails}} is a module available for [[Nginx]] and [[Apache]], that greatly simplifies setting up a Rails server environment. Nginx does not support modules as Apache and has to be compiled with {{ic|mod_rails}} in order to support Passenger; let Passenger compile it for you. As for Apache, let Passenger set up the module for you.<br />
<br />
Start by installing the 'passenger' gem:<br />
# gem install passenger<br />
<br />
If you are aiming to use [[Apache]], run:<br />
# passenger-install-apache2-module<br />
<br />
In case a rails application is deployed with a sub-URI, like http://example.com/yourapplication, some additional configuration is required, see [http://www.modrails.com/documentation/Users%20guide%20Apache.html#deploying_rails_to_sub_uri the modrails documentation]<br />
<br />
For [[Nginx]]:<br />
# passenger-install-nginx-module<br />
<br />
The installer will provide you with any additional information regarding the installation (such as installing additional libraries).<br />
<br />
To serve an application with Nginx, configure it as follows:<br />
<pre><br />
server {<br />
server_name app.example.org;<br />
root path_to_app/public; # Be sure to point to 'public' folder!<br />
passenger_enabled on;<br />
rails_env development; # Rails environment.<br />
}<br />
</pre><br />
<br />
=== Puma (with Nginx as reverse proxy server) ===<br />
<br />
[http://puma.io/ Puma] ([https://github.com/puma/puma Github Page]) is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications, and is considered the replacement for Webrick and Mongrel. It was designed to be the go-to server for Rubinius, but also works well with JRuby and MRI. While reverse proxy server would acts as a load balancer that routes all external requests to a pool of web apps.<br />
<br />
For a webserver it is better to use a server user and group, check [[Users_and_groups#Example_adding_a_user]], below use {{ic|rails}} as user name and {{ic|server}} as group name, also {{ic|my_app}} as rails app name.<br />
<br />
Start by copying your app to /var/www/my_app. And set new ownership with<br />
# cd /var/www/<br />
# chown -R rails:server my_app<br />
<br />
and permission for user with<br />
# chmod -R 775 my_app<br />
<br />
Then add puma gem in the Gemfile and install with<br />
$ cd my_app <br />
$ bundle install<br />
<br />
Also install {{ic|nginx}} by pacman.<br />
<br />
Under your app folder, create sockets, pid and log folder with<br />
$ mkdir -p shared/pids shared/sockets shared/log<br />
<br />
Backup nginx.conf with<br />
# cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup<br />
<br />
Then create a new nginx.conf file with your favorite editor, copy codes below and modify as you like:<br />
<pre><br />
#user html;<br />
worker_processes 1; # this may connect with the worker numbers puma can use.<br />
<br />
#error_log logs/error.log;<br />
#error_log logs/error.log notice;<br />
#error_log logs/error.log info;<br />
<br />
#pid logs/nginx.pid;<br />
<br />
<br />
events {<br />
worker_connections 1024;<br />
}<br />
<br />
http {<br />
upstream app {<br />
# Path to Puma SOCK file, as defined previously<br />
server unix:/var/www/my_app/shared/sockets/puma.sock;<br />
}<br />
<br />
server {<br />
listen 80;<br />
server_name localhost; # or your server name<br />
<br />
root /var/www/my_app/public;<br />
<br />
try_files $uri/index.html $uri @app;<br />
<br />
location @app {<br />
proxy_pass http://app;<br />
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />
proxy_set_header Host $http_host;<br />
proxy_redirect off;<br />
}<br />
<br />
error_page 500 502 503 504 /500.html;<br />
client_max_body_size 4G;<br />
keepalive_timeout 10;<br />
}<br />
}</pre><br />
<br />
Start nginx service with<br />
# systemctl start nginx<br />
<br />
<br />
There are several ways to start puma server, two ways are recommended below:<br />
<br />
==== Option A: With config file ====<br />
<br />
Create file config/puma.rb, copy codes below and modify as you like:<br />
<pre><br />
# Change to match your CPU core count<br />
# You can check available worker numbers with $ grep -c processor /proc/cpuinfo<br />
# also see the comment in the nginx.conf<br />
workers 2<br />
<br />
# Min and Max threads per worker<br />
#threads 1, 6<br />
<br />
app_dir = File.expand_path("../..", __FILE__)<br />
shared_dir = "#{app_dir}/shared"<br />
<br />
# Default to production<br />
#rails_env = ENV['RAILS_ENV'] || "production"<br />
#environment rails_env<br />
<br />
# Set up socket location<br />
bind "unix://#{shared_dir}/sockets/puma.sock"<br />
<br />
# Logging<br />
#stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true<br />
<br />
# Set master PID and state locations<br />
pidfile "#{shared_dir}/pids/puma.pid"<br />
#state_path "#{shared_dir}/pids/puma.state"<br />
#activate_control_app<br />
<br />
#on_worker_boot do<br />
# require "active_record"<br />
# ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished<br />
# ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])<br />
#end</pre><br />
<br />
and start server with<br />
$ bundle exec puma -C config/puma.rb<br />
<br />
You can also run it in background with parameter {{ic|-d}} and check with<br />
$ ps aux| grep puma<br />
when you want to {{ic|kill}} it.<br />
<br />
==== Option 2: by systemd ====<br />
<br />
Create a new systemd unit {{ic|puma.service}} under /usr/lib/systemd/system/ and copy codes below<br />
<pre><br />
[Unit]<br />
Description=Puma application server<br />
After=network.target<br />
<br />
[Service]<br />
WorkingDirectory=/var/www/my_app<br />
#Environment=RAILS_ENV=production<br />
User=rails<br />
PIDFile=/var/www/my_app/shared/pids/puma.pid<br />
ExecStart=/home/rails/.gem/ruby/2.2.0/bin/bundle exec \<br />
/home/rails/.gem/ruby/2.2.0/bin/puma \<br />
-b unix:///var/www/my_app/shared/sockets/puma.sock \<br />
--pidfile /var/www/my_app/shared/pids/puma.pid<br />
<br />
[Install]<br />
WantedBy=multi-user.target</pre><br />
<br />
Then start puma with<br />
# systemctl start puma<br />
<br />
For further reading take a look at [[Ruby_on_Rails#References_2]]<br />
<br />
== Databases ==<br />
<br />
Most web applications will need to interact with some sort of database. ActiveRecord (the ORM used by Rails to provide database abstraction) supports several database vendors, the most popular of which are MySQL, SQLite, and PostgreSQL.<br />
<br />
=== SQLite ===<br />
<br />
SQLite is the default lightweight database for Ruby on Rails. To enable SQLite, simply install {{Pkg|sqlite}}.<br />
<br />
=== PostgreSQL ===<br />
<br />
Install {{Pkg|postgresql}}.<br />
<br />
=== MySQL ===<br />
<br />
First, install and configure a MySQL server. Please refer to [[MySQL]] on how to do this.<br />
<br />
A gem with some native extensions is required, probably best installed as root:<br />
# gem install mysql<br />
<br />
You can generate a rails application configured for MySQL by using the {{ic|-d}} parameter:<br />
$ rails new testapp_name -d mysql<br />
<br />
You then need to edit {{ic|config/database.yml}}. Rails uses different databases for development, testing, production and other environments. Here is an example development configuration for MySQL running on localhost:<br />
<br />
development:<br />
adapter: mysql<br />
database: my_application_database<br />
username: development<br />
password: my_secret_password<br />
<br />
Note that you do not have to actually create the database using MySQL, as this can be done via Rails with:<br />
# rake db:create<br />
<br />
If no errors are shown, then your database has been created and Rails can talk to your MySQL database.<br />
<br />
== The Perfect Rails Setup ==<br />
<br />
''Phusion Passenger running multiple Ruby versions.''<br />
<br />
* [https://www.archlinux.org/ Arch Linux]: A simple, lightweight distribution. ;)<br />
* [http://www.nginx.org/ Nginx]: A fast and lightweight '''web server''' with a strong focus on high concurrency, performance and low memory usage.<br />
* [http://www.modrails.com/ Passenger] (a.k.a. mod_rails or mod_rack): Supports both Apache and Nginx web servers. It makes deployment of Ruby web applications, such as those built on Ruby on Rails web framework, a breeze.<br />
* [https://rvm.io/ Ruby Version Manager] (RVM): A command-line tool which allows you to easily install, manage, and work with multiple Ruby environments from interpreters to sets of gems. RVM lets you deploy each project with its own completely self-contained and dedicated environment —from the specific version of ruby, all the way down to the precise set of required gems to run your application—.<br />
* [http://sqlite.org/ SQLite]: The default lightweight '''database''' for Ruby on Rails.<br />
<br />
=== Step 0: SQLite ===<br />
<br />
Install {{Pkg|sqlite}}.<br />
<br />
{{note|Of course SQLite is not critical in this setup, you can use MySQL and PostgreSQL as well.}}<br />
<br />
=== Step 1: RVM ===<br />
<br />
Make a multi-user [[RVM]] installation as specified [[RVM#Multi-user_installation|here]].<br />
<br />
In the 'adding users to the rvm group' step, do<br />
# usermod -a -G rvm http<br />
# usermod -a -G rvm nobody<br />
<br />
{{ic|http}} and {{ic|nobody}} are the users related to Nginx and Passenger, respectively.<br />
<br />
{{note|Maybe adding the 'nobody' user to the 'rvm' group is not necessary.}}<br />
<br />
=== Step 2: Rubies ===<br />
<br />
Once you have a working RVM installation in your hands, it is time to install the latest Ruby interpreter<br />
{{Note|During the installation of Ruby patches will be applied. Consider installing the {{ic|base-devel}} group beforehand.}}<br />
<br />
$ rvm install 2.0.0<br />
<br />
{{Note| It may be useful to delete the 'global' gemsets of the environments that have web applications. Their gems might somehow interfere with Passenger. In that case, a {{ic|rvm 2.0.0 do gemset delete global}} is sufficient.}}<br />
<br />
=== Step 3: Nginx with Passenger support ===<br />
<br />
Run the following to allow passenger install nginx:<br />
$ rvm use 2.0.0 <br />
$ gem install passenger<br />
$ rvmsudo passenger-install-nginx-module<br />
<br />
The passenger gem will be put into the ''default'' gemset.<br />
<br />
This will download the sources of Nginx, compile and install it for you. It will guide you through all the process. Note that the default location for Nginx will be {{ic|/opt/nginx}}.<br />
<br />
{{Note|If you encounter a compilation error regarding Boost threads, see [https://bbs.archlinux.org/viewtopic.php?id&#61;139164 this] article.}}<br />
<br />
After completion, add the following two lines into the 'http block' at {{ic|/opt/nginx/conf/nginx.conf}} that look like:<br />
<br />
http { <br />
...<br />
passenger_root /usr/local/rvm/gems/ruby-2.0.0-p353/gems/passenger-3.0.9;<br />
passenger_ruby /usr/local/rvm/wrappers/ruby-2.0.0-p353/ruby;<br />
...<br />
}<br />
<br />
{{Note|This step is currently being done automatically by the installer script.}}<br />
<br />
=== Step 4: Gemsets and Apps ===<br />
<br />
For each Rails application you should have a gemset. Suppose that you want to try [http://refinerycms.com RefineryCMS] against [http://www.browsercms.org BrowserCMS], two open-source Content Management Systems based on Rails.<br />
<br />
Install RefineryCMS first:<br />
<br />
$ rvm use 2.0.0@refinery --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install refinerycms refinerycms-i18n sqlite3<br />
<br />
Deploy a RefineryCMS instance called ''refineria'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo refinerycms refineria<br />
<br />
Install BrowserCMS in a different gemset:<br />
<br />
$ rvm use 2.0.0@browser --create<br />
$ gem install rails -v 4.0.1<br />
$ gem install passenger<br />
$ gem install browsercms sqlite3<br />
<br />
Deploy a BrowserCMS instance called ''navegador'':<br />
<br />
$ cd /srv/http/<br />
$ rvmsudo browsercms demo navegador<br />
$ cd /srv/http/navegador<br />
$ rvmsudo rake db:install<br />
<br />
=== Passenger for Nginx and Passenger Standalone ===<br />
<br />
Observe that the passenger gem was installed three times and with different intentions; in the environments<br />
* ''2.0.0'' => for Nginx,<br />
* ''2.0.0@refinery'' => Standalone<br />
* ''2.0.0@browser'' => Standalone<br />
<br />
The strategy is to combine Passenger for Nginx with Passenger Standalone. One must first identify the Ruby environment (interpreter plus gemset) that one uses the most; in this setup the Ruby interpreter and the default gemset were selected. One then proceeds with setting up Passenger for Nginx to use that environment (step 3).<br />
* Applications within the chosen environment can be served as in [[#Apache.2FNginx .28using Phusion Passenger.29|Apache/Nginx (using Phusion Passenger)]], page up in this article.<br />
* All applications that are to use a different Ruby version and/or gemset can be served separately through Passenger Standalone and hook into the main web server via a reverse proxy configuration (step 6).<br />
<br />
=== Step 5: .rvmrc files and ownerships ===<br />
<br />
This step is crucial for the correct behaviour of the setup. RVM seeks for .rvmrc files when changing folders; if it finds one, it reads it. In these files normally one stores a line like<br />
rvm <ruby_version>@<gemset_name><br />
so the specified environment is set at the entrance of applications' root folder.<br />
<br />
Create /srv/http/refineria/.rvmrc doing<br />
# echo "rvm ree@refinery" > /srv/http/refineria/.rvmrc<br />
, and /srv/http/navegador/.rvmrc with<br />
# echo "rvm 2.0.0@browser" > /srv/http/navegador/.rvmrc<br />
You have to enter to both application root folders now, because every first time that RVM finds a .rvmrc it asks you if you trust the given file, consequently you must validate the two files you have just created.<br />
<br />
These files aid the programs involved to find the correct gems.<br />
<br />
Apart, if applications' files and folders are not owned by the right user you will face database write-access problems. The use of rvmsudo produces ''root''-owned archives when generated by Rails; in the other hand, ''nobody'' is the user for Passenger —if you have not changed it—: who will use and should posses them. Fix this doing<br />
# chown -R nobody.nobody /srv/http/refineria /srv/http/navegador<br />
<br />
=== Step 6: Reverse proxies ===<br />
<br />
You have to start the Passenger Standalone web servers for your applications. So, do<br />
$ cd /srv/http/refineria<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
and<br />
$ cd /srv/http/navegador<br />
$ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d<br />
. The first time that you run a Passenger Standalone it will perform a minor installation.<br />
<br />
Note that you are using ''unix domain'' sockets instead of the commonly-used ''TCP'' sockets; it turns out that unix domain are significantly faster than TCP sockets.<br />
<br />
{{note|If you are experimenting trouble with unix sockets, changing to TCP should work:<br />
rvmsudo passenger start -a 127.0.0.1 -p 3000 -d<br />
}}<br />
<br />
==== Launch Passenger Standalone daemons at system start-up ====<br />
<br />
''Do you have a script? Please post it here.''<br />
<br />
The systemd script below was made for a Typo blog I host at /srv/http/typo. It is located at /etc/systemd/system/passenger_typo.service. I set the Environment= tags (see "man systemd.exec") from the output of "rvm env". The only exception was PATH=, which I had to combine from my regular PATH and the output of rvm env.<br />
<br />
Note: If you do not set the "WorkingDirectory=" variable to your application folder, passenger will fail to find your app and will subsequently shut itself down.<br />
<br />
<pre><br />
[Unit]<br />
Description=Passenger Standalone Script for Typo<br />
After=network.target<br />
<br />
[Service]<br />
Type=forking<br />
WorkingDirectory=/srv/http/typo<br />
PIDFile=/srv/http/typo/tmp/pids/passenger.pid<br />
<br />
Environment=PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo/bin:/usr/local/rvm/gems/ruby-2.0.0-p0@global/bin:/usr/local/rvm/rubies/ruby-2.0.0-p0/bin:/usr/local/rvm/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/bin/core_perl<br />
Environment=rvm_env_string=ruby-2.0.0-p0@typo<br />
Environment=rvm_path=/usr/local/rvm<br />
Environment=rvm_ruby_string=ruby-2.0.0-p0<br />
Environment=rvm_gemset_name=typo<br />
Environment=RUBY_VERSION=ruby-2.0.0-p0<br />
Environment=GEM_HOME=/usr/local/rvm/gems/ruby-2.0.0-p0@typo<br />
Environment=GEM_PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo:/usr/local/rvm/gems/ruby-2.0.0-p0@global<br />
Environment=MY_RUBY_HOME=/usr/local/rvm/rubies/ruby-2.0.0-p0<br />
Environment=IRBRC=/usr/local/rvm/rubies/ruby-2.0.0-p0/.irbrc<br />
<br />
ExecStart=/bin/bash -c "rvmsudo passenger start --socket /srv/http/typo/tmp/sockets/passenger.socket -d"<br />
<br />
[Install]<br />
WantedBy=multi-user.target<br />
</pre><br />
<br />
=== Step 7: Deployment ===<br />
<br />
==== With subdomains ====<br />
<br />
Once again edit /opt/nginx/conf/nginx.conf to include some vital instructions:<br />
<br />
<pre><br />
## RefineryCMS ##<br />
<br />
server {<br />
server_name refinery.domain.com;<br />
root /srv/http/refineria/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/refineria/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
<br />
## BrowserCMS ##<br />
<br />
server {<br />
server_name browser.domain.com;<br />
root /srv/http/navegador/public;<br />
location / {<br />
proxy_pass http://unix:/srv/http/navegador/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
{{note|Or if using TCP sockets, configure the ''proxy_pass'' directive like<br />
<pre>proxy_pass http://127.0.0.1:3000;</pre><br />
}}<br />
<br />
==== Without subdomains ====<br />
<br />
If you for some reason do not want to host each application on its own subdomain but rather in a url like: {{ic|site.com/railsapp}} then you could do something like this in your config:<br />
<br />
<pre><br />
server {<br />
server_name site.com;<br />
#Base for the html files etc<br />
root /srv/http/;<br />
<br />
#First application you want hosted under domain site.com/railsapp<br />
location /railsapp {<br />
root /srv/http/railsapp/public;<br />
#you may need to change passenger_base_uri to be the uri you want to point at, ie:<br />
#passenger_base_uri /railsapp;<br />
#but probably only if you are using the other solution with passenger phusion<br />
proxy_pass http://unix:/srv/http/railsapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
<br />
#Second applicatino you want hosted under domain site.com/anotherapp<br />
location /anotherapp {<br />
root /srv/http/anotherapp/public;<br />
#same thing about the passenger_base_uri here, but with value /anotherapp instead<br />
proxy_pass http://unix:/srv/http/anotherapp/tmp/sockets/passenger.socket;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
</pre><br />
<br />
At this point you are in conditions to run Nginx with:<br />
<br />
# systemctl start nginx<br />
<br />
and to access both CMSs through ''refinery.domain.com'' and ''browser.domain.com''.<br />
<br />
=== References ===<br />
<br />
* http://beginrescueend.com/integration/passenger<br />
* http://blog.phusion.nl/2010/09/21/phusion-passenger-running-multiple-ruby-versions<br />
<br />
== See also ==<br />
<br />
* [[Ruby]]<br />
* [[Nginx]]<br />
* [[LAMP]]<br />
* [[MySQL]]<br />
<br />
== References ==<br />
<br />
* Ruby on Rails http://rubyonrails.org/download.<br />
* Mongrel http://mongrel.rubyforge.org.</div>Stbinanhttps://wiki.archlinux.org/index.php?title=PRIME&diff=363912PRIME2015-03-04T16:17:18Z<p>Stbinan: /* When an application is rendered with the discrete card, it only renders a black screen */</p>
<hr />
<div>[[Category:Graphics]]<br />
[[zh-CN:PRIME]]<br />
{{Expansion|The list of drivers that support PRIME is incomplete.}}<br />
PRIME is a technology used to manage hybrid graphics found on recent laptops ([[NVIDIA Optimus|Optimus for NVIDIA]], AMD Dynamic Switchable Graphics for ATI).<br />
<br />
The following drivers support it:<br />
<br />
* {{Pkg|xf86-video-nouveau}}<br />
* {{Pkg|xf86-video-ati}}<br />
* {{Pkg|xf86-video-intel}}<br />
<br />
== Installation ==<br />
<br />
First, check the list of video cards attached to your display:<br />
<br />
{{hc|$ xrandr --listproviders|<br />
Providers: number : 2<br />
Provider 0: id: 0x7d cap: 0xb, Source Output, Sink Output, Sink Offload crtcs: 3 outputs: 4 associated providers: 1 name:Intel<br />
Provider 1: id: 0x56 cap: 0xf, Source Output, Sink Output, Source Offload, Sink Offload crtcs: 6 outputs: 1 associated providers: 1 name:radeon<br />
}}<br />
<br />
We can see that there are two graphic cards: Intel, the integrated card (id 0x7d), and Radeon, the discrete card (id 0x56), which should be used for GPU-intensive applications. We can see that, by default, Intel is always used:<br />
<br />
{{hc|<nowiki>$ glxinfo | grep "OpenGL renderer"</nowiki>|<br />
OpenGL renderer string: Mesa DRI Intel(R) Ivybridge Mobile<br />
}}<br />
<br />
The command {{ic|xrandr --setprovideroffloadsink provider sink}} can be used to make a render offload provider send its output to the sink provider (the provider which has a display connected). The provider and sink identifiers can be numeric (0x7d, 0x56) or a case-sensitive name (Intel, radeon). Example:<br />
<br />
$ xrandr --setprovideroffloadsink radeon Intel<br />
<br />
Now, you can use your discrete card for the applications who need it the most (for example games, 3D modellers...):<br />
<br />
{{hc|<nowiki>$ DRI_PRIME=1 glxinfo | grep "OpenGL renderer"</nowiki>|<br />
OpenGL renderer string: Gallium 0.4 on AMD TURKS<br />
}}<br />
<br />
Other applications will still use the less power-hungry integrated card. These settings are lost once the X server restarts, you may want to make a script and auto-run it at the startup of your desktop environment (alternatively, put it in {{ic|/etc/X11/xinit/xinitrc.d/}}). This may reduce your battery life and increase heat though.<br />
<br />
== Troubleshooting ==<br />
<br />
=== XRandR specifies only 1 output provider ===<br />
<br />
Delete/move /etc/X11/xorg.conf file and any other files relating to GPUs in /etc/X11/xorg.conf.d/. Restart the X server after this change.<br />
<br />
If the video driver is blacklisted in {{ic|/etc/modprobe.d/}}, load the module and restart X. This may be the case if you use the bbswitch module for Nvidia GPUs.<br />
<br />
=== When an application is rendered with the discrete card, it only renders a black screen ===<br />
<br />
In some cases PRIME needs a composition manager to properly work. If your window manager doesn’t do compositing, you can use [[xcompmgr]] on top of it.<br />
<br />
If you use Xfce, you can go to Menu->Settings->Window Manager Tweaks->Compositor and enable compositing, then try again your application. <br />
<br />
==== Black screen with GL-based compositors ====<br />
Currently there are issues with GL-based compositors and PRIME offloading. While Xrender-based compositors (xcompmgr, xfwm, compton's default backend, cairo-compmgr, and a few others) will work without issue, GL-based compositors (Mutter/muffin, Compiz, compton with GLX backend, Kwin's OpenGL backend, etc) will initially show a black screen, as if there was no compositor running. While you can force an image to appear by resizing the offloaded window, this is not a practical solution as it will not work for things such as full screen Wine applications. This means that desktop environments such as GNOME3 and Cinnamon have issues with using PRIME offloading.<br />
<br />
Additionally if you are using an Intel IGP you might be able to fix the GL Compositing issue by running the IGP as UXA instead of SNA, however this may cause issues with the offloading process (ie, xrandr --listproviders may not list the discrete GPU).</div>Stbinanhttps://wiki.archlinux.org/index.php?title=X2Go&diff=357494X2Go2015-01-21T12:34:25Z<p>Stbinan: /* Configuring the Server */</p>
<hr />
<div>[[Category:Remote Desktop]]<br />
With [http://wiki.x2go.org X2Go] you can access your desktop using another computer -- that means both LAN and internet connections. The transmission is done using the ssh protocol, so it is encrypted. By using the free nx libraries from NoMachine, a very acceptable performance in both speed and responsiveness is achieved. Even an ISDN connection runs smoothly.<br />
<br />
This makes it possible to connect your laptop to any computer with the environment, applications, and performance of the remote desktop. It is also possible to have a bunch of computers connected to a single server (terminal-server, thin-client).<br />
<br />
Clients are available for Linux (Qt4), Windows, and Mac. The latter two can be downloaded directly as binary from the X2Go homepage.<br />
<br />
== X2Go and Arch Linux ==<br />
<br />
Arch Linux X2Go packages are available in the [[official repositories]]. Currently the {{Pkg|x2goserver}} and {{Pkg|x2goclient}} are available. The LDAP based usermanagement suite is not yet finished, nor are tools that make X2Go more convenient for use in schools and thin client environments.<br />
<br />
== Installation and configuration ==<br />
<br />
=== Configuring the Server ===<br />
====Install the x2goserver package:====<br />
Install {{Pkg|x2goserver}} from the [[official repositories]].<br />
<br />
====Install and configure the ssh-daemon:====<br />
# pacman -S openssh<br />
# pacman -S xorg-xauth xorg-xhost<br />
<br />
Enable X11 forwarding:<br />
in /etc/ssh/sshd_config<br />
set AllowTcpForwarding and X11UseLocalhost to yes, set X11DisplayOffset to 10 (those may be the default values if nothing has been changed, see man sshd_config)<br />
set X11Forwarding to yes<br />
<br />
Then start sshd service:<br />
# systemctl start sshd.service<br />
<br />
To have sshd started at boot time:<br />
<br />
# systemctl enable sshd.service<br />
<br />
====Load the fuse module:====<br />
This makes it possible for the server to access files on the client computer.<br />
<br />
# modprobe fuse<br />
<br />
To have this module loaded at boot time, you also have to put it into /etc/modules-load.d, e.g.<br />
<br />
{{hc|/etc/modules-load.d/fuse.conf|<br />
fuse}}<br />
<br />
====Initialize the SQL database (and start the SQL server):====<br />
<br />
You can choose to use either Postgres or SQLite database, the latter does not need a running server.<br />
<br />
Initialize SQLite db:<br />
# x2godbadmin --createdb<br />
<br />
Start the x2goserver:<br />
# systemctl start x2goserver.service<br />
<br />
If you want to have the X2Go server started at boot time:<br />
<br />
# systemctl enable x2goserver.service<br />
<br />
====Check SSH daemon configuration to allow non-English session:====<br />
<br />
If you are using other than POSIX (C) locale, you may want to add the following line to /etc/ssh/sshd_config:<br />
<br />
# Allow client to pass locale environment variables<br />
AcceptEnv LANG LC_*<br />
<br />
Then restart the daemon (as root):<br />
# systemctl restart sshd.service<br />
<br />
== Desktop Shadowing ==<br />
To gain access to the "local desktop" (as opposed to a unique session/desktop environment) you need to install [https://aur.archlinux.org/packages/x2godesktopsharing x2godesktopsharing] from the [https://aur.archlinux.org AUR]. Then, launch x2godesktopsharing from either the command-line or your desktop environment's menu (usually under "Internet"). <br />
<br />
== Configuration of the Client ==<br />
<br />
'''Install the client:'''<br />
<br />
{{Pkg|x2goclient}} is available in the [[official repositories]]. It is a Qt GUI app, although you can also check-out the command line options by running<br />
<br />
x2goclient --help<br />
<br />
'''Double check ssh'''<br />
<br />
Convince yourself that you can open a ssh-session from the client to<br />
the server (host). <br />
<br />
ssh YourUsername_onServer@yourhost_or_ip<br />
<br />
Within the local network this should not be a problem. The way you<br />
connect from beyond your network, lets say the internet, to your<br />
computer at home is a question of how your network is build up. This<br />
would go beyond the scope of this article. Therefore here only a few<br />
items: <br />
* A port has to be opened at the router resp. gateway which forwards requests to your server, and there especially to the sshd-port (which normally is 22). To prevent a big part of the portscan attacks it is probably better to have 222 as publicly reachable port.<br />
* To prevent you from having the need to keep your public IP address in mind (especially if this changes dynamically) it is advisable to use a dynamic DNS-Service (DynDNS, DynIP). Many routers are preconfigured to be reachable under a name rather than an IP address.<br />
<br />
'''Enough preliminaries! Now to the x2goclient. Run it:'''<br><br />
x2goclient<br />
This opens the client application. You can now create several sessions, which then appear on the right side and can be selected by a mouse click. Each entry consists of your username on the server, hostname and IP and the port for ssh-connection. Furthermore you can define several speed profiles (coming from modem up to LAN) and the desktop environment you want to start remotely.<br />
<br />
'''Common mistakes:'''<br><br />
Do not simply choose the defaults of KDE or Gnome, since the executables startkde or startgnome are usually not in the PATH when logging in using ssh. Use full paths to startkde or<br />
startgnome. You can also start openbox or another window manager. <br />
<br />
You should be asked for your password for your user at the server now and after login you will see the X2Go logo for a short time, and -- voila -- the desktop.<br />
<br />
'''Exchange data between client and server(desktop)'''<br><br />
On the x2goclient (e.g. laptop) local directories could be shared. The server will use fuse and sshfs to access this directory and mount it to a subdirectory media<br />
of your home directory on the server. This enables you to have access to laptop data on your server or to exchange files. It is also possible to mount these shares<br />
automatically at each session start.<br />
<br />
'''To leave a session temporarily'''<br><br />
Another special feature of X2Go is the possibility of suspending a session. This means you can leave a session on one client and reopen<br />
it even from another client at the same point. This can be used to to start a session in the LAN and to reopen it later on a laptop.<br />
The session data are stored and administered in a postgres database on the server in the meanwhile. The state of the sessions is protocolled<br />
by a process named x2gocleansessions.<br />
<br />
== Various ==<br />
<br />
'''Workaround for failing compositing window manager for remote session'''<br />
<br />
This is useful for situations, when the computer running x2goserver is used also for local sessions with e.g. compiz as the window manager. For remote connections with x2goclient, compiz fails to load and metacity should be used instead. The following is for GNOME, but could be modified for other desktop environments. (Getting compiz ready is not part of this how-to.)<br />
<br />
Create /usr/local/share/applications/gnome-wm-test.desktop:<br />
<br />
[Desktop Entry]<br />
Type=Application<br />
Encoding=UTF-8<br />
Name=gnome-wm-test<br />
Exec=/usr/local/bin/gnome-wm-test.sh<br />
NoDisplay=true<br />
<br />
Create script /usr/local/bin/gnome-wm-test.sh:<br />
<br />
#!/bin/sh<br />
# Script for choosing compiz when possible, otherwise metacity<br />
# Proper way to use this script is to set the key to mk-gnome-wm<br />
# /desktop/gnome/session/required_components/windowmanager<br />
xdpyinfo 2> /dev/null | grep -q "^ *Composite$" 2> /dev/null<br />
IS_X_COMPOSITED=$?<br />
if [ $IS_X_COMPOSITED -eq 0 ] ; then<br />
gtk-window-decorator &<br />
WM="compiz ccp --indirect-rendering --sm-client-id $DESKTOP_AUTOSTART_ID"<br />
else<br />
WM="metacity --sm-client-id=$DESKTOP_AUTOSTART_ID"<br />
fi<br />
exec bash -c "$WM"<br />
<br />
Modify the following gconf key to start the session with gnome-wm-test window manager:<br />
<br />
$ gconftool-2 --type string --set /desktop/gnome/session/required_components/windowmanager "gnome-wm-test"<br />
<br />
== Future ==<br />
<br />
At the moment the package consists mainly of the x2goserver and the x2goclient. It is planned to add in near future: <br />
* LDAP-Integration. This allow the administration of users, sessions and logins using LDAP. This is an interesting feature for schools or companies. For this purpose there are control programs which integrate themselves into the KDE Control Center.<br />
* The option to use x2goclient as a login screen for thin clients.<br />
* The possibility to use local devices (CD, floppy, USB-stick) remotely and transparently. <br />
<br />
Questions and problems? You could contact me also directly.<br />
[[Special:Emailuser/Gerbra|GerBra]]<br />
<br />
(Many thanks to Stefan Husmann for translation from archlinux.de wiki)<br />
<br />
== Troubleshooting ==<br />
<br />
* If you get the following authentication error.<br />
<br />
Authentification Failed:<br />
The host key for this server was not found but an othertype of key exists.<br />
An Attacker might change the default server key to confuse <br />
your client into thinking the key does not exist<br />
<br />
Then delete the servers entry from your ~/.ssh/known_hosts file and then retry to authenticate.<br />
<br />
== Links ==<br />
<br />
[http://wiki.archlinux.de/?title=Bild:X2go-1.png Screenshot KDE-Session]<br />
<br />
[http://wiki.archlinux.de/?title=Bild:X2go-2.png Screenshot configuration dialog]<br />
<br />
[http://x2go.org Project page]</div>Stbinanhttps://wiki.archlinux.org/index.php?title=RVM&diff=357018RVM2015-01-19T05:16:02Z<p>Stbinan: /* A cautionary action */</p>
<hr />
<div>[[Category:Development]]<br />
[[de:RVM]]<br />
{{Related articles start}}<br />
{{Related|Rbenv}}<br />
{{Related|Chruby}}<br />
{{Related|Ruby}}<br />
{{Related articles end}}<br />
[http://rvm.io/ RVM] (Ruby Version Manager) is a command line tool which allows us to easily install, manage and work with multiple [[Ruby]] environments from interpreters to sets of gems.<br />
<br />
There exists a similar application that you may also want to consider: [[rbenv]].<br />
<br />
== Installing RVM ==<br />
<br />
The install process is very easy, and is the very same for any distro, including Archlinux. You have two choices, one system-wide, another as a user. The first is for production servers, or if your are alone on your machine. You'll need root privileges. The second is the recommended for multiple users on the same machine (like a development test box). If you do not know which to choose, start with a single user installation.<br />
<br />
The upstream instructions for installing RVM should just work. The install script is aware enough to tell you what packages you need to install on Archlinux to make different rubies work. This usually involves gcc and some other stuff needed to compile ruby.<br />
<br />
As an observation, '''installing RVM with gem is not recommended anymore'''. This article uses the [http://rvm.io/rvm/install/ recommended documentation] with minor tweaks to make it work on Archlinux.<br />
<br />
=== Pre-requisites ===<br />
<br />
Before starting, you will need the following to get the installation process going:<br />
<br />
$ pacman -S git curl<br />
<br />
=== Single-user installation ===<br />
<br />
{{Note|This will install to your home directory only (~/.rvm), and won't touch the standard Arch ruby package, which is in /usr.}}<br />
<br />
For most purposes, the recommended installation method is single-user, which is a self-contained RVM installation in a user's home directory.<br />
<br />
Use the script that rvm docs recommends to install. Make sure to run this script as the user for whom you want RVM installed (i.e. your normal user that you use for development).<br />
<br />
To check the script before running it, do:<br />
<br />
$ curl -L get.rvm.io > rvm-install<br />
<br />
Inspect the file, and then run it with:<br />
<br />
$ bash < ./rvm-install<br />
<br />
You can also install without checking the script, to do this run:<br />
<br />
$ curl -L get.rvm.io | bash -s stable<br />
<br />
(to install a specific version replace ''stable'' with, for example, ''-- --version 1.13.0'')<br />
<br />
After the script has finished, then add the following line to the end of your ~/.bash_login or ~/.bashrc (or ~/.zprofile or whatever):<br />
<br />
$ <nowiki>[[ -s "$HOME/.rvm/scripts/rvm" ]]</nowiki> && source "$HOME/.rvm/scripts/rvm"<br />
<br />
Now, close out your current shell or terminal session and open a new one. (You may attempt reloading your ~/.bash_login with the following command:<br />
<br />
$ source ~/.bash_login<br />
<br />
However, closing out your current shell or terminal and opening a new one is the preferred way for initial installations.)<br />
<br />
=== Multi-user installation ===<br />
<br />
{{Note|This will install to /usr/local/rvm, and won't touch the standard Arch ruby package, which is in /usr. }}<br />
<br />
System-wide installation is a similar procedure to the single user install. However, instead run the install script with sudo. '''Do not run the installer directly as root!'''<br />
<br />
$ curl -L get.rvm.io | sudo bash -s stable<br />
<br />
(to install a specific version replace ''stable'' with, for example, ''-- --version 1.13.0'')<br />
<br />
After the script has finished, add yourself and your users to the 'rvm' group. (The installer does not auto-add any users to the rvm group. Admins must do this.) For each one, repeat:<br />
<br />
$ sudo usermod -a -G rvm <user><br />
<br />
'''Group memberships are only evaluated at login time'''. Log the users out, then back in. You too: close out your current shell or terminal session and open a new one. (You may attempt reloading your ~/.bash_login with the following command:<br />
<br />
$ source ~/.bash_login<br />
<br />
However, closing out your current shell or terminal and opening a new one is the preferred way for initial installations. Alternatively, you can use the "newgrp rvm" command and check with "id" to see whether the shell has picked up the new group membership of your user)<br />
<br />
{{Note|Remember to change the line [ [ -s $HOME/.rvm/scripts/rvm ] ] && source $HOME/.rvm/scripts/rvm to the system-wide location changing $HOME to /usr/local/}}<br />
<br />
RVM will be automatically configured for every user on the system (in opposite to the single-user installation); this is accomplished by loading /etc/profile.d/rvm.sh on login. Archlinux defaults to parsing /etc/profile which contains the logic to load all files residing in the /etc/profile.d/ directory.<br />
<br />
Before installing gems with multi-user rvm, make sure that /etc/gemrc does not have the line "gem: --user-install". If it does you need to comment it out otherwise the gems will install to the wrong place.<br />
<br />
'''You only use the sudo command during the install process'''. In multi-user configurations, any operations which require sudo access must use the ''rvmsudo'' command which preserves the RVM environment and passes this on to sudo. There are very few cases where rvmsudo is required once the core install is completed, except for when updating RVM itself. There is never a reason to use sudo post-install. rvmsudo should only be needed for updating with<br />
<br />
$ rvmsudo rvm get head<br />
<br />
===== A cautionary action =====<br />
<br />
In order to prevent the installation breakage by this cause, you may add this configuration to your /etc/sudoers file with command: {{ic|#su -c visudo}}<br />
<br />
{{bc|1=<br />
## Cmnd alias specification<br />
Cmnd_Alias RVM = /usr/local/rvm/rubies/<ruby_interpreter>/bin/gem, \<br />
/usr/local/rvm/rubies/<another_ruby_interpreter>/bin/gem, \<br />
/usr/local/rvm/bin/rvm<br />
<br />
## User privilege specification<br />
root ALL=(ALL) ALL<br />
<br />
## Uncomment to allow members of group wheel to execute any command<br />
%wheel ALL=(ALL) ALL, !RVM<br />
}}<br />
<br />
Where ''<ruby_interpreter>'' would be —for example— ruby-1.9.2-p290.<br />
<br />
== Post Installation ==<br />
<br />
After the installation, check everything worked with this command:<br />
<br />
$ type rvm | head -n1<br />
<br />
The response should be:<br />
<br />
$ rvm is a function<br />
<br />
If you receive rvm: not found, you may need to source your ~/.bash_login (or wherever you put the line above):<br />
<br />
$ . ~/.bash_login<br />
<br />
Check if the rvm function is working:<br />
<br />
$ rvm notes<br />
<br />
Finally, see if there are any dependency requirements for your installation by running:<br />
<br />
$ rvm requirements<br />
<br />
(Follow the returned instructions if any.)<br />
<br />
'''Very important''': whenever you upgrade RVM in the future, you should always run ''rvm notes'' and ''rvm requirements'' as this is usually where you will find details on any major changes and/or additional requirements '''to ensure your installation stays working'''.<br />
<br />
=== Some extras ===<br />
<br />
You may put in your ~/.bashrc the following lines to get some useful features:<br />
{{bc|1=<br />
# Display the current RVM ruby selection<br />
PS1="\$(/usr/local/rvm/bin/rvm-prompt) $PS1"<br />
<br />
# RVM bash completion<br />
<nowiki>[[ -r /usr/local/rvm/scripts/completion ]]</nowiki> && . /usr/local/rvm/scripts/completion<br />
}}<br />
<br />
Or if you're running as a single user:<br />
{{bc|1=<br />
# RVM bash completion<br />
<nowiki>[[ -r "$HOME/.rvm/scripts/completion" ]]</nowiki> && source "$HOME/.rvm/scripts/completion"<br />
}}<br />
<br />
== Using RVM ==<br />
<br />
The RVM documentation is ''quite'' comprehensive and explanatory. However, here are some RVM usage examples to get you started.<br />
<br />
=== Rubies ===<br />
<br />
==== Installing environments ====<br />
<br />
To see what Ruby environments are available to install, run:<br />
<br />
$ rvm list known<br />
<br />
To install one, run:<br />
<br />
$ rvm install <ruby_version><br />
<br />
For example, to install Ruby 1.9.2 one would run the following command:<br />
<br />
$ rvm install 1.9.2<br />
<br />
This should download, configure and install Ruby 1.9.2 in the place you installed RVM. For example, if you did a single user install, it will be in ~/.rvm/rubies/1.9.2.<br />
<br />
You can define a default ruby interpreter by doing:<br />
<br />
$ rvm use <ruby_version> --default<br />
<br />
If not, the default environment will be the system ruby in /usr —if you have installed one using pacman— or none.<br />
<br />
==== Switching environments ====<br />
<br />
To switch from one environment to another simply run:<br />
<br />
$ rvm use <ruby_version><br />
<br />
For example to switch to Ruby 1.8.7 one would run the following command:<br />
<br />
$ rvm 1.8.7<br />
<br />
(As you see, the flag ''use'' is not really necessary.)<br />
<br />
You should get a message telling you the switch worked. It can be confirmed by running:<br />
<br />
$ ruby --version<br />
<br />
Note that this environment will only be used in the current shell. You can open another shell and select a different environment for that one in parallel.<br />
<br />
In case you have set a default interpreter as explained above, you can do the switch with:<br />
<br />
$ rvm default<br />
<br />
==== System ruby ====<br />
<br />
If you wish the ruby interpreter that is outside RVM (i.e. the one installed in /usr by the standard Archlinux package), you can switch to it using:<br />
<br />
$ rvm system<br />
<br />
==== Listing environments ====<br />
<br />
To see all installed Ruby environments, run the following command:<br />
<br />
$ rvm list<br />
<br />
If you've installed a few rubies, this might generate a list like so:<br />
<br />
rvm Rubies<br />
jruby-1.5.0 [ [i386-java] ]<br />
=> ruby-1.8.7-p249 [ i386 ]<br />
ruby-1.9.2-head [ i386 ]<br />
System Ruby<br />
system [ i386 ]<br />
<br />
The ASCII arrow indicates which environment is currently enabled. In this case, it is Ruby 1.8.7. This could be confirmed by running:<br />
<br />
$ ruby --version<br />
ruby 1.8.7 (2010-01-10 patchlevel 249) [i686-linux]<br />
<br />
=== Gemsets ===<br />
<br />
RVM has a valued feature called gemsets which enables you to store different sets of gems in compartmentalized independent ruby setups. This means that ruby, gems and irb are all separate and self-contained from the system and each other.<br />
<br />
==== Creating ====<br />
<br />
Gemsets must be created before being used. To create a new gemset for the current ruby, do this:<br />
<br />
$ rvm use <ruby_version><br />
$ rvm gemset create <gemset_name><br />
<br />
Alternatively, if you prefer the shorthand syntax offered by rvm use, employ the --create option like so:<br />
<br />
$ rvm use <ruby_version>@<gemset_name> --create<br />
<br />
You can also specify a default gemset for a given ruby interpreter, by doing:<br />
<br />
$ rvm use <ruby_version>@<gemset_name> --default<br />
<br />
==== Using ====<br />
<br />
Tip: remove gems that reside in system priore RVM installation with:<br />
$ gem list --local | awk '{print "gem uninstall " $1}' | bash<br />
<br />
and check what's left:<br />
<br />
$ gem list --local<br />
<br />
To use a gemset:<br />
<br />
$ rvm gemset use <gemset_name><br />
<br />
You can switch to a gemset as you start to use a ruby, by appending @<gemset_name> to the end of the ruby selector string:<br />
<br />
$ rvm use <ruby_version>@<gemset_name><br />
<br />
===== Notes =====<br />
<br />
When you install a ruby environment, it comes with two gemsets out of the box, their names are ''default'' and ''global''. You will usually find in the latter some pre-installed common gems, while the former always starts empty. <br />
<br />
A little bit about where the default and global gemsets differ: When you do not use a gemset at all, you get the gems in the default set. If you use a specific gemset (say @testing), it will inherit gems from that ruby's @global. The global gemset is to allow you to share gems to all your gemsets.<br />
<br />
==== Gems! ====<br />
<br />
Within a gemset, you can utilize usual RubyGems commands<br />
$ gem install <gem><br />
to add,<br />
$ gem uninstall <gem><br />
to remove gems, and<br />
$ gem list<br />
to view installed ones.<br />
<br />
If you are deploying to a server, or you do not want to wait around for rdoc and ri to install for each gem, you can disable them for gem installs and updates. Just add these two lines to your ~/.gemrc or /etc/gemrc:<br />
<br />
install: --no-document<br />
update: --no-document<br />
<br />
==== Listing ====<br />
<br />
To see the name of the current gemset:<br />
<br />
$ rvm gemset name<br />
<br />
To list all named gemsets for the current ruby interpreter:<br />
<br />
$ rvm gemset list<br />
<br />
To list all named gemsets for all interpreters:<br />
<br />
$ rvm gemset list_all<br />
<br />
==== Deleting ====<br />
<br />
This action removes the current gemset:<br />
<br />
$ rvm gemset use <gemset_name><br />
$ rvm gemset delete <gemset_name><br />
<br />
By default, rvm deletes gemsets from the currently selected Ruby interpreter. To delete a gemset from a different interpreter, say 1.9.2, run your command this way:<br />
<br />
$ rvm 1.9.2 do gemset delete <gemset_name><br />
<br />
==== Emptying ====<br />
<br />
This action removes all gems installed in the gemset:<br />
<br />
$ rvm gemset use <gemset_name><br />
$ rvm gemset empty <gemset_name><br />
<br />
=== RVM ===<br />
<br />
==== Updating ====<br />
<br />
To upgrade to the most recent release version:<br />
<br />
$ rvm get latest<br />
<br />
Upgrading to the latest repository source version (the most bugfixes):<br />
<br />
$ rvm get head<br />
<br />
Remember to use rvmsudo for multi-user setups. Update often!<br />
<br />
==== Uninstalling ====<br />
<br />
Executing<br />
<br />
$ rvm implode<br />
<br />
is going to wipe out the RVM installation —cleanly—.<br />
<br />
=== Further Reading ===<br />
<br />
This is just a simple introduction to switching ruby versions with RVM and managing different set of gems in different environments. There is lots more that you can do with it! For more information, consult the very comprehensive RVM documentation. [https://rvm.beginrescueend.com/rvm/basics/ This page] is a good place to start.<br />
<br />
== Troubleshooting ==<br />
<br />
You will need to take care with rvm installations, since ArchLinux is very well updated, and some earlier ruby's patchlevels do not like it. RVM many times do not choose the latest patchlevel version to install, and you'll need to check manually on the [http://www.ruby-lang.org/en/news/ ruby website], and force RVM to install it.<br />
<br />
==== "data definition has no type or storage class" ====<br />
<br />
This appears to be specific to 1.8.7, but if you get this error while compiling the following steps will fix your problem:<br />
<br />
$ cd src/ruby-1.8.7-p334/ext/dl<br />
$ rm callback.func<br />
$ touch callback.func<br />
$ ruby mkcallback.rb >> callback.func<br />
$ rm cbtable.func<br />
$ touch cbtable.func<br />
$ ruby mkcbtable.rb >> cbtable.func<br />
<br />
Naturally, substitute the actual build path to your source, which will be something like ~/.rvm/src/.<br />
<br />
==== Ruby 1.8.x won't compile with RVM ====<br />
<br />
This is a known issue on Arch Linux, and is caused by a problem with openssl. Arch uses openssl 1.0, lower patchlevels of 1.8.7 assumes 0.9. <br />
<br />
Certain patch levels may not build (p352 for example), p299 should work fine and can be installed using the following command:<br />
<br />
$ rvm remove 1.8.7<br />
$ rvm install 1.8.7-p299<br />
<br />
Another approach is to install local openssl via RVM:<br />
<br />
$ rvm pkg install openssl<br />
$ rvm remove 1.8.7<br />
$ rvm install 1.8.7 -C --with-openssl-dir=$HOME/.rvm/usr<br />
<br />
It may be necessary to patch 1.8.7:<br />
<br />
$ wget http://redmine.ruby-lang.org/attachments/download/1931/stdout-rouge-fix.patch<br />
$ rvm remove 1.8.7<br />
$ rvm install --patch Downloads/stdout-rouge-fix.patch ruby-1.8.7-p352<br />
<br />
==== Ruby 1.9.1 won't compile with RVM ====<br />
<br />
Like with 1.8.x, earlier patchlevels do not like the OpenSSL 1.0. Then you can use the very same solution above, by installing openssl locally on RVM.<br />
<br />
$ rvm pkg install openssl<br />
$ rvm remove 1.9.1<br />
$ rvm install 1.9.1 -C --with-openssl-dir=$HOME/./rvm/usr<br />
<br />
The patchlevels >p378 have a problem with gem paths, when $GEM_HOME is set. The problem is known and fixed in 1.9.2. (http://redmine.ruby-lang.org/issues/3584). If you really need 1.9.1 please use p378.<br />
<br />
$ rvm install 1.9.1-p378 -C --with-openssl-dir=$HOME/.rvm/usr<br />
<br />
== See Also ==<br />
<br />
* [http://rvm.io/ RVM project website].<br />
* [[RubyOnRails#Option_C:_The_Perfect_Rails_Setup|The Perfect Rails Setup]].</div>Stbinanhttps://wiki.archlinux.org/index.php?title=GoAgent_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)&diff=355881GoAgent (简体中文)2015-01-08T13:54:16Z<p>Stbinan: /* 亚全局 */</p>
<hr />
<div>[[Category:简体中文]]<br />
[[Category:Networking (简体中文)]]<br />
GoAgent 是使用 [[Python]] 和 Google App Engine SDK 编写的免费代理软件,利用 Google App Engine 充当代理服务器。<br />
<br />
GoAgent 的运行原理于其他代理工具基本相同,其借由 Google App Engine 的服务器作为中传,将数据数据包后传送至 Google 服务器,再由 Google 服务器转发至目的服务器,接收数据时方法也类似。相对其他代理工具而言 GoAgent 要稳定许多。<br />
<br />
==安装==<br />
[[Official repositories (简体中文)|官方软件源]]已收录 {{Pkg|goagent}},直接用 [[pacman (简体中文)|pacman]] 安装即可.<br />
<br />
==配置==<br />
<br />
===服务器端===<br />
申请 Google Appengine 并创建 appid 。具体教程可参考[http://www.douban.com/note/262773856/ 此]。<br />
<br />
{{注意|appid请勿包含android/ios等关键词,否则有可能被某些网站识别为移动设备用户。}}<br />
<br />
上传(使用root用户,否则会出现权限不够的问题):<br />
{{bc|# python2 /usr/share/goagent/server/uploader.py}}<br />
{{注意|原来的uploader.zip在新版本已经不存在了,代替它的是uploader.py。如出现不能上传的情况可以去github上git下来用里面的那个uploader.py试试}}<br />
{{注意|无效的 hosts 可能会导致上传失败,可尝试清空 {{ic|/etc/resolv.conf}} 再上传。<br />
将来的版本更新可能会要求重新上传。请参看[https://code.google.com/p/goagent/#更新历史_2013 官方的更新历史],带有[是]标记的则需要重新上传。此外是否需要重新上传是相对于前一版的,若您之前版本与当前版本之间某一版或多版带有[是]仍然需要重新上传}}<br />
{{提示|首次上传后,可以再任意修改 Appid,无需再重新上传,不过最好重启以生效}}<br />
<br />
执行时会要求您再输入 appid ,请保持与 {{ic|proxy.ini}} 中已有的一致;接着还要输入 Google 邮箱及密码。<br />
<br />
{{注意|若您的 Google 账户有开通两步验证功能,则密码应为16位的应用程序专用密码。}}<br />
<br />
至此,代理服务器 127.0.0.1:8087 已搭建完毕。现在以 [[Chromium (简体中文)|Chrome/Chromium]] 为例,示范使用代理服务器的方法。<br />
<br />
{{注意|若浏览器类软件要通过 GoAgent 代理访问 Internet,可能均需要导入证书}}<br />
<br />
===客户端===<br />
{{提示|goagent 3.1.2-2 引入了用户配置文件(goagent.user.ini), 配置方法有所变动. 如果您是从旧版本升级, 可以在按照如下方法配置后放心删除以前的 /etc/goagent.pacsave. 此次变动之后, 您将不再需要在每次升级后合并该配置文件.}}<br />
打开 {{ic|/etc/goagent}} (默认情况下该文件为空), 增加类似下面的段落:<br />
<br />
[gae]<br />
appid = your_appid<br />
password = yourpassword<br />
<br />
修改 {{ic|your_appid}} 为您所申请的 appid。如果您申请了多个 appid 用于负载均衡, 用竖线 | 分隔多个id (不含空格).<br />
如果您使用的服务端没有配置密码, 可以省略掉 {{ic|code=password =}} 开头的一整行.<br />
<br />
goagent 3.1.5-1 新增 dnsproxy 功能, 基本配置依然是修改 {{ic|/etc/goagent}} 文件, 加入类似以下内容:<br />
<br />
[dns]<br />
enable = 1<br />
listen = 127.0.0.1:5353<br />
<br />
如果希望 DNS 服务跑在 53 端口, 需要使用 root 用户运行服务. 新增 {{ic|/etc/systemd/system/goagent.service.d/use_root.conf}} 文件, 加入以下内容即可:<br />
<br />
[Service]<br />
User=root<br />
<br />
====Chrome/Chromium====<br />
请安装 [https://chrome.google.com/webstore/detail/proxy-switchysharp/dpplabbmogkhghncfbfdeeokoefdjegm SwitchySharp 插件],接着导入[https://goagent.googlecode.com/files/SwitchyOptions.bak 该设置]。可参考[https://code.google.com/p/switchysharp/wiki/SwitchySharp_GFW_List_2 该扩展提供的图解流程]。<br />
<br />
打开设置-管理证书-授权中心-Authorities,导入 {{ic|/usr/share/goagent/local/CA.crt}},弹出窗口的三条选项均勾选。<br />
<br />
{{注意|如果第一次安装 GoAgent 尝试到此步骤时发现该文件不存在,请先启动一次 GoAgent 后再重新尝试。}}<br />
<br />
====亚全局====<br />
在 Unix 和 GNU/Linux 中,大多 HTTP 应用程序均支持调用环境变量 {{ic|http_proxy}} 和 {{ic|https_proxy}} 进行代理,就像 lynx、 [[wget]] 和 curl,甚至也包括了 [[Chromium (简体中文)]] 和 [[git (简体中文)]]。此外该环境变量的大小写其实并没有统一标准,有个别程序就只支持全大写的环境变量。所以为方便起见,直接在 {{ic|~/.bash_profile}} 或 {{ic|~/.zshenv}} 添加以下即可:<br />
<br />
export http_proxy=http://127.0.0.1:8087/<br />
export https_proxy=$http_proxy<br />
export HTTP_PROXY=$http_proxy<br />
export HTTPS_PROXY=$HTTP_PROXY<br />
<br />
{{注意|虽然 Chrome 浏览器也可以通过其环境变量进行全局代理从而不再需要 Proxy Extension,但不建议这么做,因为会导致访问国内网站的速度下降,甚至个别网站就拒绝境外代理访问,例如收录了大量版权视频的网站。}}<br />
<br />
再执行以下命令,以导入证书进 Arch Linux。至此,就可以实现 Arch Linux 亚全局代理:<br />
<br />
# mkdir /usr/share/ca-certificates/goagent<br />
# cp /usr/share/goagent/local/CA.crt /usr/share/ca-certificates/goagent/GoAgent.crt<br />
# echo 'goagent/GoAgent.crt' >> /etc/ca-certificates/conf.d/goagent.conf<br />
# update-ca-certificates<br />
<br />
2014-12-11 官方发布新闻证书导入采用新方法,上述方法需要改进 [https://www.archlinux.org/news/ca-certificates-update/ ca-certificates update]<br />
<br />
==运行==<br />
===以 daemon 形式运行 (推荐)===<br />
# systemctl start goagent<br />
若想开机自启动,执行:<br />
# systemctl enable goagent<br />
<br />
{{提示|可通过{{ic|# journalctl -u goagent}}来查询日志}}<br />
<br />
====屏蔽日志输出====<br />
如果不想让 GoAgent 的输出信息进入日志,可以通过屏蔽 goagent.service 里的对应行解决,方法如下:<br />
<br />
1. 创建目录 {{ic|/etc/systemd/system/goagent.service.d}}<br />
<br />
2. 创建文件 {{ic|/etc/systemd/system/goagent.service.d/nostdout.conf}}, 写入如下内容:<br />
[Service]<br />
StandardOutput=null<br />
<br />
====日志输出至TTY====<br />
如果不想让 GoAgent 的输出信息进入日志,但是又想得到 GoAgent 的运行情况,可以通过修改 goagent.service 里的对应行解决,方法如下:<br />
<br />
1. 创建目录 {{ic|/etc/systemd/system/goagent.service.d}}<br />
<br />
2. 创建文件 {{ic|/etc/systemd/system/goagent.service.d/totty.conf}}, 写入如下内容:<br />
[Service]<br />
StandardOutput=tty<br />
StandardError=tty<br />
TTYPath=/dev/ttyX #X为数字,ttyX不能正在被使用,推荐为1-12之间的整数,用Ctrl+Alt+FX切换至<br />
#TTYVTDisallocate=yes #若需要在启动前清理所在TTY的虚拟终端,取消本行前的注释<br />
<br />
3.运行:<br />
# systemctl daemon-reload && systemctl restart goagent<br />
<br />
===手动运行(不推荐+不支持)===<br />
由于不明原因,总有个别用户无法成功以 daemon 形式运行GoAgent,可改试手动运行:<br />
$ sudo -u nobody python2 /usr/share/goagent/local/goagent<br />
<br />
若是在更新后发生问题,可尝试清空{{ic|/usr/share/goagent/local/certs}}目录,甚至卸载并手动删除{{ic|/etc/}}和{{ic|/usr/share/}}下的有关文件,然后重新安装和配置。<br />
<br />
==疑难解答==<br />
<br />
===Firefox 31.0 及以上版本提示安全连接失败:证书包含未知的关键扩展。===<br />
<br />
从 Firefox 31.0 开始默认使用新的 mozilla::pkix 为证书验证库。GoAgent 证书已被证实和此证书验证机制不兼容。新证书认证会导致提示“安全连接失败:证书包含未知的关键扩展。 (错误码: sec_error_unknown_critical_extension)”。解决的方法有两种,推荐使用解决方法 1 。<br />
<br />
====解决方法 1 (推荐)====<br />
<br />
=====重新生成新的 GoAgent 证书=====<br />
取得 Root 权限并执行以下命令:<br />
<br />
# rm /usr/share/goagent/local/CA.crt<br />
# rm -rf /usr/share/goagent/local/certs<br />
# systemctl restart goagent<br />
<br />
=====在 Firefox 中导入新证书=====<br />
在 Firefox 中点击右上角的菜单按钮(三道杠),在弹出的菜单中点击“首选项”(齿轮图标),打开首选项页面,点击"高级"-"证书"-"查看证书“,弹出一个新窗口,点击”证书机构“,在列表中找到"GoAgent CA"项并选中该项,点击"删除或不信任",即完成删除原来的证书。点击"导入",弹出文件选择窗口,进入目录 /usr/share/goagent/local/ ,选择文件 CA.crt 并点击打开,即完成导入新证书。点击确定关闭弹出窗口,重新启动 Firefox 即可。<br />
<br />
====解决方法 2====<br />
在 Firefox 的地址栏上输入 about:config ,在输入框中输入 security.use_mozillapkix_verification ,在下面的列表中找到该项并双击修改为 false 。<br />
<br />
==参阅==<br />
* [https://code.google.com/p/goagent/ GoAgent 在 Google Code 的主页]<br />
* [https://github.com/goagent/goagent GoAgent 在 GitHub 的主页]<br />
* 两位开发者的 Twitter 帐号:[https://twitter.com/hewigovens @hewigovens],[https://twitter.com/phuslu @phuslu]<br />
* [https://groups.google.com/forum/#!topic/archlinux-cn/_PPW2dZHltE 讨论亚全局代理的 Email List]</div>Stbinanhttps://wiki.archlinux.org/index.php?title=GoAgent_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)&diff=355880GoAgent (简体中文)2015-01-08T13:53:15Z<p>Stbinan: /* 亚全局 */</p>
<hr />
<div>[[Category:简体中文]]<br />
[[Category:Networking (简体中文)]]<br />
GoAgent 是使用 [[Python]] 和 Google App Engine SDK 编写的免费代理软件,利用 Google App Engine 充当代理服务器。<br />
<br />
GoAgent 的运行原理于其他代理工具基本相同,其借由 Google App Engine 的服务器作为中传,将数据数据包后传送至 Google 服务器,再由 Google 服务器转发至目的服务器,接收数据时方法也类似。相对其他代理工具而言 GoAgent 要稳定许多。<br />
<br />
==安装==<br />
[[Official repositories (简体中文)|官方软件源]]已收录 {{Pkg|goagent}},直接用 [[pacman (简体中文)|pacman]] 安装即可.<br />
<br />
==配置==<br />
<br />
===服务器端===<br />
申请 Google Appengine 并创建 appid 。具体教程可参考[http://www.douban.com/note/262773856/ 此]。<br />
<br />
{{注意|appid请勿包含android/ios等关键词,否则有可能被某些网站识别为移动设备用户。}}<br />
<br />
上传(使用root用户,否则会出现权限不够的问题):<br />
{{bc|# python2 /usr/share/goagent/server/uploader.py}}<br />
{{注意|原来的uploader.zip在新版本已经不存在了,代替它的是uploader.py。如出现不能上传的情况可以去github上git下来用里面的那个uploader.py试试}}<br />
{{注意|无效的 hosts 可能会导致上传失败,可尝试清空 {{ic|/etc/resolv.conf}} 再上传。<br />
将来的版本更新可能会要求重新上传。请参看[https://code.google.com/p/goagent/#更新历史_2013 官方的更新历史],带有[是]标记的则需要重新上传。此外是否需要重新上传是相对于前一版的,若您之前版本与当前版本之间某一版或多版带有[是]仍然需要重新上传}}<br />
{{提示|首次上传后,可以再任意修改 Appid,无需再重新上传,不过最好重启以生效}}<br />
<br />
执行时会要求您再输入 appid ,请保持与 {{ic|proxy.ini}} 中已有的一致;接着还要输入 Google 邮箱及密码。<br />
<br />
{{注意|若您的 Google 账户有开通两步验证功能,则密码应为16位的应用程序专用密码。}}<br />
<br />
至此,代理服务器 127.0.0.1:8087 已搭建完毕。现在以 [[Chromium (简体中文)|Chrome/Chromium]] 为例,示范使用代理服务器的方法。<br />
<br />
{{注意|若浏览器类软件要通过 GoAgent 代理访问 Internet,可能均需要导入证书}}<br />
<br />
===客户端===<br />
{{提示|goagent 3.1.2-2 引入了用户配置文件(goagent.user.ini), 配置方法有所变动. 如果您是从旧版本升级, 可以在按照如下方法配置后放心删除以前的 /etc/goagent.pacsave. 此次变动之后, 您将不再需要在每次升级后合并该配置文件.}}<br />
打开 {{ic|/etc/goagent}} (默认情况下该文件为空), 增加类似下面的段落:<br />
<br />
[gae]<br />
appid = your_appid<br />
password = yourpassword<br />
<br />
修改 {{ic|your_appid}} 为您所申请的 appid。如果您申请了多个 appid 用于负载均衡, 用竖线 | 分隔多个id (不含空格).<br />
如果您使用的服务端没有配置密码, 可以省略掉 {{ic|code=password =}} 开头的一整行.<br />
<br />
goagent 3.1.5-1 新增 dnsproxy 功能, 基本配置依然是修改 {{ic|/etc/goagent}} 文件, 加入类似以下内容:<br />
<br />
[dns]<br />
enable = 1<br />
listen = 127.0.0.1:5353<br />
<br />
如果希望 DNS 服务跑在 53 端口, 需要使用 root 用户运行服务. 新增 {{ic|/etc/systemd/system/goagent.service.d/use_root.conf}} 文件, 加入以下内容即可:<br />
<br />
[Service]<br />
User=root<br />
<br />
====Chrome/Chromium====<br />
请安装 [https://chrome.google.com/webstore/detail/proxy-switchysharp/dpplabbmogkhghncfbfdeeokoefdjegm SwitchySharp 插件],接着导入[https://goagent.googlecode.com/files/SwitchyOptions.bak 该设置]。可参考[https://code.google.com/p/switchysharp/wiki/SwitchySharp_GFW_List_2 该扩展提供的图解流程]。<br />
<br />
打开设置-管理证书-授权中心-Authorities,导入 {{ic|/usr/share/goagent/local/CA.crt}},弹出窗口的三条选项均勾选。<br />
<br />
{{注意|如果第一次安装 GoAgent 尝试到此步骤时发现该文件不存在,请先启动一次 GoAgent 后再重新尝试。}}<br />
<br />
====亚全局====<br />
在 Unix 和 GNU/Linux 中,大多 HTTP 应用程序均支持调用环境变量 {{ic|http_proxy}} 和 {{ic|https_proxy}} 进行代理,就像 lynx、 [[wget]] 和 curl,甚至也包括了 [[Chromium (简体中文)]] 和 [[git (简体中文)]]。此外该环境变量的大小写其实并没有统一标准,有个别程序就只支持全大写的环境变量。所以为方便起见,直接在 {{ic|~/.bash_profile}} 或 {{ic|~/.zshenv}} 添加以下即可:<br />
<br />
export http_proxy=http://127.0.0.1:8087/<br />
export https_proxy=$http_proxy<br />
export HTTP_PROXY=$http_proxy<br />
export HTTPS_PROXY=$HTTP_PROXY<br />
<br />
{{注意|虽然 Chrome 浏览器也可以通过其环境变量进行全局代理从而不再需要 Proxy Extension,但不建议这么做,因为会导致访问国内网站的速度下降,甚至个别网站就拒绝境外代理访问,例如收录了大量版权视频的网站。}}<br />
<br />
再执行以下命令,以导入证书进 Arch Linux。至此,就可以实现 Arch Linux 亚全局代理:<br />
<br />
# mkdir /usr/share/ca-certificates/goagent<br />
# cp /usr/share/goagent/local/CA.crt /usr/share/ca-certificates/goagent/GoAgent.crt<br />
# echo 'goagent/GoAgent.crt' >> /etc/ca-certificates/conf.d/goagent.conf<br />
# update-ca-certificates<br />
<br />
2014-12-11 官方发布新闻证书导入采用新方法,上述方法需要改进 [https://www.archlinux.org/news/ca-certificates-update/ ca-certificates update]]<br />
<br />
==运行==<br />
===以 daemon 形式运行 (推荐)===<br />
# systemctl start goagent<br />
若想开机自启动,执行:<br />
# systemctl enable goagent<br />
<br />
{{提示|可通过{{ic|# journalctl -u goagent}}来查询日志}}<br />
<br />
====屏蔽日志输出====<br />
如果不想让 GoAgent 的输出信息进入日志,可以通过屏蔽 goagent.service 里的对应行解决,方法如下:<br />
<br />
1. 创建目录 {{ic|/etc/systemd/system/goagent.service.d}}<br />
<br />
2. 创建文件 {{ic|/etc/systemd/system/goagent.service.d/nostdout.conf}}, 写入如下内容:<br />
[Service]<br />
StandardOutput=null<br />
<br />
====日志输出至TTY====<br />
如果不想让 GoAgent 的输出信息进入日志,但是又想得到 GoAgent 的运行情况,可以通过修改 goagent.service 里的对应行解决,方法如下:<br />
<br />
1. 创建目录 {{ic|/etc/systemd/system/goagent.service.d}}<br />
<br />
2. 创建文件 {{ic|/etc/systemd/system/goagent.service.d/totty.conf}}, 写入如下内容:<br />
[Service]<br />
StandardOutput=tty<br />
StandardError=tty<br />
TTYPath=/dev/ttyX #X为数字,ttyX不能正在被使用,推荐为1-12之间的整数,用Ctrl+Alt+FX切换至<br />
#TTYVTDisallocate=yes #若需要在启动前清理所在TTY的虚拟终端,取消本行前的注释<br />
<br />
3.运行:<br />
# systemctl daemon-reload && systemctl restart goagent<br />
<br />
===手动运行(不推荐+不支持)===<br />
由于不明原因,总有个别用户无法成功以 daemon 形式运行GoAgent,可改试手动运行:<br />
$ sudo -u nobody python2 /usr/share/goagent/local/goagent<br />
<br />
若是在更新后发生问题,可尝试清空{{ic|/usr/share/goagent/local/certs}}目录,甚至卸载并手动删除{{ic|/etc/}}和{{ic|/usr/share/}}下的有关文件,然后重新安装和配置。<br />
<br />
==疑难解答==<br />
<br />
===Firefox 31.0 及以上版本提示安全连接失败:证书包含未知的关键扩展。===<br />
<br />
从 Firefox 31.0 开始默认使用新的 mozilla::pkix 为证书验证库。GoAgent 证书已被证实和此证书验证机制不兼容。新证书认证会导致提示“安全连接失败:证书包含未知的关键扩展。 (错误码: sec_error_unknown_critical_extension)”。解决的方法有两种,推荐使用解决方法 1 。<br />
<br />
====解决方法 1 (推荐)====<br />
<br />
=====重新生成新的 GoAgent 证书=====<br />
取得 Root 权限并执行以下命令:<br />
<br />
# rm /usr/share/goagent/local/CA.crt<br />
# rm -rf /usr/share/goagent/local/certs<br />
# systemctl restart goagent<br />
<br />
=====在 Firefox 中导入新证书=====<br />
在 Firefox 中点击右上角的菜单按钮(三道杠),在弹出的菜单中点击“首选项”(齿轮图标),打开首选项页面,点击"高级"-"证书"-"查看证书“,弹出一个新窗口,点击”证书机构“,在列表中找到"GoAgent CA"项并选中该项,点击"删除或不信任",即完成删除原来的证书。点击"导入",弹出文件选择窗口,进入目录 /usr/share/goagent/local/ ,选择文件 CA.crt 并点击打开,即完成导入新证书。点击确定关闭弹出窗口,重新启动 Firefox 即可。<br />
<br />
====解决方法 2====<br />
在 Firefox 的地址栏上输入 about:config ,在输入框中输入 security.use_mozillapkix_verification ,在下面的列表中找到该项并双击修改为 false 。<br />
<br />
==参阅==<br />
* [https://code.google.com/p/goagent/ GoAgent 在 Google Code 的主页]<br />
* [https://github.com/goagent/goagent GoAgent 在 GitHub 的主页]<br />
* 两位开发者的 Twitter 帐号:[https://twitter.com/hewigovens @hewigovens],[https://twitter.com/phuslu @phuslu]<br />
* [https://groups.google.com/forum/#!topic/archlinux-cn/_PPW2dZHltE 讨论亚全局代理的 Email List]</div>Stbinanhttps://wiki.archlinux.org/index.php?title=GoAgent_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)&diff=296518GoAgent (简体中文)2014-02-08T01:26:09Z<p>Stbinan: /* 手动运行(不推荐+不支持) */</p>
<hr />
<div>[[Category:简体中文]]<br />
[[Category:Networking (简体中文)]]<br />
GoAgent 是使用 [[Python]] 和 Google App Engine SDK 编写的免费代理软件,利用 Google App Engine 充当代理服务器。<br />
<br />
GoAgent 的运行原理于其他代理工具基本相同,其借由 Google App Engine 的服务器作为中传,将数据数据包后传送至 Google 服务器,再由 Google 服务器转发至目的服务器,接收数据时方法也类似。相对其他代理工具而言 GoAgent 要稳定许多。<br />
<br />
==安装==<br />
[[Official Repositories (简体中文)|官方软件源]]已收录 {{Pkg|goagent}},直接用 [[pacman (简体中文)|pacman]] 安装即可.<br />
<br />
==配置==<br />
<br />
===服务器端===<br />
申请 Google Appengine 并创建 appid 。具体教程可参考[http://www.douban.com/note/262773856/ 此]。<br />
<br />
{{注意|appid请勿包含android/ios等关键词,否则有可能被某些网站识别为移动设备用户。}}<br />
<br />
上传:<br />
{{bc|# python2 /usr/share/goagent/server/uploader.zip}}<br />
{{注意|无效的 hosts 可能会导致上传失败,可尝试清空 {{ic|/etc/resolv.conf}} 再上传。<br />
将来的版本更新可能会要求重新上传。请参看[https://code.google.com/p/goagent/#更新历史_2013 官方的更新历史],带有[是]标记的则需要重新上传。此外是否需要重新上传是相对于前一版的,若您之前版本与当前版本之间某一版或多版带有[是]仍然需要重新上传}}<br />
{{提示|首次上传后,可以再任意修改 Appid,无需再重新上传,不过最好重启以生效}}<br />
<br />
执行时会要求您再输入 appid ,请保持与 {{ic|proxy.ini}} 中已有的一致;接着还要输入 Google 邮箱及密码。<br />
<br />
{{注意|若您的 Google 账户有开通两步验证功能,则密码应为16位的应用程序专用密码。}}<br />
<br />
至此,代理服务器 127.0.0.1:8087 已搭建完毕。现在以 [[Chromium (简体中文)|Chrome/Chromium]] 为例,示范使用代理服务器的方法。<br />
<br />
{{注意|若浏览器类软件要通过 GoAgent 代理访问 Internet,可能均需要导入证书}}<br />
<br />
===客户端===<br />
{{提示|goagent 3.1.2-2 引入了用户配置文件(goagent.user.ini), 配置方法有所变动. 如果您是从旧版本升级, 可以在按照如下方法配置后放心删除以前的 /etc/goagent.pacsave. 此次变动之后, 您将不再需要在每次升级后合并该配置文件.}}<br />
打开 {{ic|/etc/goagent}} (默认情况下该文件为空), 增加类似下面的段落:<br />
<br />
[gae]<br />
appid = your_appid<br />
password = yourpassword<br />
<br />
修改 {{ic|your_appid}} 为您所申请的 appid。如果您申请了多个 appid 用于负载均衡, 用竖线 | 分隔多个id (不含空格).<br />
如果您使用的服务端没有配置密码, 可以省略掉 {{ic|code=password =}} 开头的一整行.<br />
<br />
goagent 3.1.5-1 新增 dnsproxy 功能, 基本配置依然是修改 {{ic|/etc/goagent}} 文件, 加入类似以下内容:<br />
<br />
[dns]<br />
enable = 1<br />
listen = 127.0.0.1:5353<br />
<br />
如果希望 DNS 服务跑在 53 端口, 需要使用 root 用户运行服务. 新增 {{ic|/etc/systemd/system/goagent.service.d/use_root.conf}} 文件, 加入以下内容即可:<br />
<br />
[Service]<br />
User=root<br />
<br />
====Chrome/Chromium====<br />
请安装 [https://chrome.google.com/webstore/detail/proxy-switchysharp/dpplabbmogkhghncfbfdeeokoefdjegm SwitchySharp 插件],接着导入[https://goagent.googlecode.com/files/SwitchyOptions.bak 该设置]。可参考[https://code.google.com/p/switchysharp/wiki/SwitchySharp_GFW_List_2 该扩展提供的图解流程]。<br />
<br />
打开设置-管理证书-授权中心-Authorities,导入 {{ic|/usr/share/goagent/local/CA.crt}},弹出窗口的三条选项均勾选。<br />
<br />
{{注意|如果第一次安装 GoAgent 尝试到此步骤时发现该文件不存在,请先启动一次 GoAgent 后再重新尝试。}}<br />
<br />
====亚全局====<br />
在 Unix 和 GNU/Linix 中,大多 HTTP 应用程序均支持调用环境变量 {{ic|http_proxy}} 和 {{ic|https_proxy}} 进行代理,就像 lynx、 [[wget]] 和 curl,甚至也包括了 [[Chromium (简体中文)]] 和 [[git (简体中文)]]。此外该环境变量的大小写其实并没有统一标准,有个别程序就只支持全大写的环境变量。所以为方便起见,直接在 {{ic|~/.bash_profile}} 或 {{ic|~/.zshenv}} 添加以下即可:<br />
<br />
export http_proxy=http://127.0.0.1:8087/<br />
export https_proxy=$http_proxy<br />
export HTTP_PROXY=$http_proxy<br />
export HTTPS_PROXY=$HTTP_PROXY<br />
<br />
{{注意|虽然 Chrome 浏览器也可以通过其环境变量进行全局代理从而不再需要 Proxy Extension,但不建议这么做,因为会导致访问国内网站的速度下降,甚至个别网站就拒绝境外代理访问,例如收录了大量版权视频的网站。}}<br />
<br />
再执行以下命令,以导入证书进 Arch Linux。至此,就可以实现 Arch Linux 亚全局代理:<br />
<br />
# mkdir /usr/local/share/ca-certificates/GoAgent<br />
# cp /usr/share/goagent/local/CA.crt /usr/local/share/ca-certificates/GoAgent<br />
# update-ca-certificates<br />
<br />
==运行==<br />
<br />
===以 daemon 形式运行 (推荐)===<br />
# systemctl start goagent<br />
若想开机自启动,执行:<br />
# systemctl enable goagent<br />
<br />
{{提示|可通过{{ic|# journalctl -u goagent}}来查询日志}}<br />
<br />
====屏蔽日志输出====<br />
如果不想让 GoAgent 的输出信息进入日志,可以通过屏蔽 goagent.service 里的对应行解决,方法如下:<br />
<br />
1. 创建目录 {{ic|/etc/systemd/system/goagent.service.d}}<br />
<br />
2. 创建文件 {{ic|/etc/systemd/system/goagent.service.d/nostdout.conf}}, 写入如下内容:<br />
[Service]<br />
StandardOutput=null<br />
<br />
===手动运行(不推荐+不支持)===<br />
由于不明原因,总有个别用户无法成功以daemon形式运行GoAgent,可改试手动运行:<br />
# python2 /usr/share/goagent/local/goagent<br />
<br />
若是更新goagent后造成的,可尝试卸载并手动删除/etc/下有关goagent的文件和/usr/share/下的goagent文件夹并重新安装配置。<br />
<br />
==参阅==<br />
* [https://code.google.com/p/goagent/ GoAgent 在 Google Code 的主页]<br />
* [https://github.com/goagent/goagent GoAgent 在 GitHub 的主页]<br />
* 两位开发者的 Twitter 帐号:[https://twitter.com/hewigovens @hewigovens],[https://twitter.com/phuslu @phuslu]<br />
* [https://groups.google.com/forum/#!topic/archlinux-cn/_PPW2dZHltE 讨论亚全局代理的 Email List]</div>Stbinan