2024-11-17 20:22:35 +00:00
<!DOCTYPE HTML>
< html lang = "en" class = "light sidebar-visible" dir = "ltr" >
< head >
<!-- Book generated using mdBook -->
< meta charset = "UTF-8" >
< title > Install host - ctrl< / title >
<!-- Custom HTML head -->
< meta name = "description" content = "" >
< meta name = "viewport" content = "width=device-width, initial-scale=1" >
< meta name = "theme-color" content = "#ffffff" >
< link rel = "icon" href = "favicon.svg" >
< link rel = "shortcut icon" href = "favicon.png" >
< link rel = "stylesheet" href = "css/variables.css" >
< link rel = "stylesheet" href = "css/general.css" >
< link rel = "stylesheet" href = "css/chrome.css" >
< link rel = "stylesheet" href = "css/print.css" media = "print" >
<!-- Fonts -->
< link rel = "stylesheet" href = "FontAwesome/css/font-awesome.css" >
< link rel = "stylesheet" href = "fonts/fonts.css" >
<!-- Highlight.js Stylesheets -->
< link rel = "stylesheet" href = "highlight.css" >
< link rel = "stylesheet" href = "tomorrow-night.css" >
< link rel = "stylesheet" href = "ayu-highlight.css" >
<!-- Custom theme stylesheets -->
<!-- Provide site root to javascript -->
< script >
var path_to_root = "";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
< / script >
<!-- Start loading toc.js asap -->
< script src = "toc.js" > < / script >
< / head >
< body >
< div id = "body-container" >
<!-- Work around some values being stored in localStorage wrapped in quotes -->
< script >
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') & & theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') & & sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
< / script >
<!-- Set the theme before any content is loaded, prevents flash -->
< script >
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
const html = document.documentElement;
html.classList.remove('light')
html.classList.add(theme);
html.classList.add("js");
< / script >
< input type = "checkbox" id = "sidebar-toggle-anchor" class = "hidden" >
<!-- Hide / unhide sidebar before it is displayed -->
< script >
var sidebar = null;
var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
} else {
sidebar = 'hidden';
}
sidebar_toggle.checked = sidebar === 'visible';
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
< / script >
< nav id = "sidebar" class = "sidebar" aria-label = "Table of contents" >
<!-- populated by js -->
< mdbook-sidebar-scrollbox class = "sidebar-scrollbox" > < / mdbook-sidebar-scrollbox >
< noscript >
< iframe class = "sidebar-iframe-outer" src = "toc.html" > < / iframe >
< / noscript >
< div id = "sidebar-resize-handle" class = "sidebar-resize-handle" >
< div class = "sidebar-resize-indicator" > < / div >
< / div >
< / nav >
< div id = "page-wrapper" class = "page-wrapper" >
< div class = "page" >
< div id = "menu-bar-hover-placeholder" > < / div >
< div id = "menu-bar" class = "menu-bar sticky" >
< div class = "left-buttons" >
< label id = "sidebar-toggle" class = "icon-button" for = "sidebar-toggle-anchor" title = "Toggle Table of Contents" aria-label = "Toggle Table of Contents" aria-controls = "sidebar" >
< i class = "fa fa-bars" > < / i >
< / label >
< button id = "theme-toggle" class = "icon-button" type = "button" title = "Change theme" aria-label = "Change theme" aria-haspopup = "true" aria-expanded = "false" aria-controls = "theme-list" >
< i class = "fa fa-paint-brush" > < / i >
< / button >
< ul id = "theme-list" class = "theme-popup" aria-label = "Themes" role = "menu" >
< li role = "none" > < button role = "menuitem" class = "theme" id = "light" > Light< / button > < / li >
< li role = "none" > < button role = "menuitem" class = "theme" id = "rust" > Rust< / button > < / li >
< li role = "none" > < button role = "menuitem" class = "theme" id = "coal" > Coal< / button > < / li >
< li role = "none" > < button role = "menuitem" class = "theme" id = "navy" > Navy< / button > < / li >
< li role = "none" > < button role = "menuitem" class = "theme" id = "ayu" > Ayu< / button > < / li >
< / ul >
< button id = "search-toggle" class = "icon-button" type = "button" title = "Search. (Shortkey: s)" aria-label = "Toggle Searchbar" aria-expanded = "false" aria-keyshortcuts = "S" aria-controls = "searchbar" >
< i class = "fa fa-search" > < / i >
< / button >
< / div >
< h1 class = "menu-title" > ctrl< / h1 >
< div class = "right-buttons" >
< a href = "print.html" title = "Print this book" aria-label = "Print this book" >
< i id = "print-button" class = "fa fa-print" > < / i >
< / a >
< / div >
< / div >
< div id = "search-wrapper" class = "hidden" >
< form id = "searchbar-outer" class = "searchbar-outer" >
< input type = "search" id = "searchbar" name = "searchbar" placeholder = "Search this book ..." aria-controls = "searchresults-outer" aria-describedby = "searchresults-header" >
< / form >
< div id = "searchresults-outer" class = "searchresults-outer hidden" >
< div id = "searchresults-header" class = "searchresults-header" > < / div >
< ul id = "searchresults" >
< / ul >
< / div >
< / div >
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
< script >
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
< / script >
< div id = "content" class = "content" >
< main >
< h1 id = "install-on-a-host" > < a class = "header" href = "#install-on-a-host" > Install on a host< / a > < / h1 >
< p > Start up a local nats message broker if you don't already have one.< / p >
< pre > < code class = "language-bash" > docker run -p 4444:4444 nats -p 4444
< / code > < / pre >
< p > Build the ctrl binary from the source code.< / p >
< pre > < code class = "language-bash" > git clone git@github.com:postmannen/ctrl.git
cd cmd/ctrl
go run build
< / code > < / pre >
< p > Copy the binary to < code > /usr/local< / code > .< / p >
< pre > < code class = "language-bash" > mkdir -p /usr/local/ctrl
cp ./ctrl /usr/local/ctrl
< / code > < / pre >
< pre > < code class = "language-bash" >
For testing we create a folder for the node to store it's data.
```bash
cd /usr/local/ctrl
mkdir node1
cd node1
< / code > < / pre >
< p > ctrl will create all the folders needed like etc, var and more in the current directory where it was started if they don't already exist. This behaviour can be changed with flags or env variables.< / p >
< p > Create a .env file for the startup options. Flags can also be used.< / p >
< pre > < code class = "language-bash" > cat < < EOF > .env
NODE_NAME="node1"
BROKER_ADDRESS="127.0.0,1:4444"
ENABLE_DEBUG=1
START_PUB_REQ_HELLO=60
IS_CENTRAL_ERROR_LOGGER=0
EOF
< / code > < / pre >
< p > Start up ctrl. ctrl will automatically used the local .env file we created.< / p >
< pre > < code class = "language-bash" > ../usr/local/ctrl/ctrl
< / code > < / pre >
< p > If you open another window, and go to the < code > /usr/local/ctrl/node1< / code > you should see that ctrl have created the directory structure for you with ./etc, ./var, ./directoryfolder and so on.< / p >
< p > Prepare and send a message. We send messages by copying them into the ./readfolder where ctrl automatically will pick it up, and process it.< / p >
< pre > < code class = "language-yaml" > cat < < EOF > msg.yaml
---
- toNodes:
- node1
method: REQCliCommand
methodArgs:
- "bash"
- "-c"
- |
echo "some config line" > /etc/my-service-config.1
echo "some config line" > /etc/my-service-config.2
echo "some config line" > /etc/my-service-config.3
systemctl restart my-service
replyMethod: REQNone
ACKTimeout: 0
EOF
cp msg.yaml readfolder
< / code > < / pre >
< p > With the above message we send to ourselves since we only got 1 node running. To start up more nodes repeat the above steps, replace.< / p >
< h2 id = "run-as-service" > < a class = "header" href = "#run-as-service" > Run as service< / a > < / h2 >
< p > Create a systemctl unit file to run ctrl as a service on the host< / p >
< pre > < code class = "language-bash" > progName="ctrl"
systemctlFile=/etc/systemd/system/$progName.service
cat > $systemctlFile < < EOF
[Unit]
Description=http-> ${progName} service
Documentation=https://github.com/postmannen/ctrl
After=network-online.target nss-lookup.target
Requires=network-online.target nss-lookup.target
[Service]
ExecStart=env CONFIG_FOLDER=/usr/local/${progName}/etc /usr/local/${progName}/${progName}
[Install]
WantedBy=multi-user.target
EOF
systemctl enable $progName.service & &
systemctl start $progName.service
< / code > < / pre >
< / main >
< nav class = "nav-wrapper" aria-label = "Page navigation" >
<!-- Mobile navigation buttons -->
< a rel = "prev" href = "user_guide_install_docker.html" class = "mobile-nav-chapters previous" title = "Previous chapter" aria-label = "Previous chapter" aria-keyshortcuts = "Left" >
< i class = "fa fa-angle-left" > < / i >
< / a >
2024-11-18 10:27:32 +00:00
< a rel = "next prefetch" href = "core_messaging_overview.html" class = "mobile-nav-chapters next" title = "Next chapter" aria-label = "Next chapter" aria-keyshortcuts = "Right" >
< i class = "fa fa-angle-right" > < / i >
< / a >
2024-11-17 20:22:35 +00:00
< div style = "clear: both" > < / div >
< / nav >
< / div >
< / div >
< nav class = "nav-wide-wrapper" aria-label = "Page navigation" >
< a rel = "prev" href = "user_guide_install_docker.html" class = "nav-chapters previous" title = "Previous chapter" aria-label = "Previous chapter" aria-keyshortcuts = "Left" >
< i class = "fa fa-angle-left" > < / i >
< / a >
2024-11-18 10:27:32 +00:00
< a rel = "next prefetch" href = "core_messaging_overview.html" class = "nav-chapters next" title = "Next chapter" aria-label = "Next chapter" aria-keyshortcuts = "Right" >
< i class = "fa fa-angle-right" > < / i >
< / a >
2024-11-17 20:22:35 +00:00
< / nav >
< / div >
<!-- Livereload script (if served using the cli tool) -->
< script >
const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";
const socket = new WebSocket(wsAddress);
socket.onmessage = function (event) {
if (event.data === "reload") {
socket.close();
location.reload();
}
};
window.onbeforeunload = function() {
socket.close();
}
< / script >
< script >
window.playground_copyable = true;
< / script >
< script src = "elasticlunr.min.js" > < / script >
< script src = "mark.min.js" > < / script >
< script src = "searcher.js" > < / script >
< script src = "clipboard.min.js" > < / script >
< script src = "highlight.js" > < / script >
< script src = "book.js" > < / script >
<!-- Custom JS scripts -->
< / div >
< / body >
< / html >