Adding Files

Joe Kaiser edited this page Jan 25, 2018 · 6 revisions

Adding Files

Whatever you can do in a shell, you can do during install.

Our assumption is that when a machine comes up, it should be exactly the way you want at first boot. This way you're certain your site specific customization is going to run once you hit the install/reinstall button, because you've already done the hard configuration scripting to make it so.

Which means you probably don't want to recreate all of that work just because you've started using a new tool. You've already figured it out, you don't want to do it again, and you probably can't remember why you do some of the things you do in those scripts. We'll discuss how to modify a cart to:

  • Not lose work you've already done.
  • Put your already existing config files where they belong: on the installing node.

site-custom cart example continued

In the Adding RPMS section, we started configuring an site-custom cart as an example -- we'll continue to use it here.

To properly have a fortune displayed when a user logs-in, you either have to put "fortune" in their .bashrc (untenable) or make it run automatically. Since /etc/profile.d has environment scripts, we'll put it there.

(Please note, the odds of you allowing users to login into the backends is probably not really a good idea, but for the sake of example, we are assuming this here.)

Go to the nodes directory of your cart:

# cd /export/stack/carts/site-custom/nodes

Edit cart-site-custom-backend.xml.

We are most concerned with what goes on between the:

<stack:script stack:stage="install-post"> </stack:script> tags.

This runs during the post-install configuration. It maps to the %post stanza in kickstart.

A <stack:file> tag must be placed between <stack:script> tags.

So in a script tag with the stage set to "install-post" we are going to add a file to the /etc/profile.d directory.

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh">
#!/bin/bash
fortune
</stack:file>
</stack:script>

This is the default structure for adding a file. If you don't set permissions, default is 644, default owner is root:root. You can set these options though, in the <stack:file> tag.

Other options

If you need to make it executable, you can set the permissions:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh" perms="0755">
#!/bin/bash
fortune
</stack:file>
</stack:script>

And, if you need to change owner/group:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh" owner="root:apache" perms="0755">
#!/bin/bash
fortune
</stack:file>
</stack:script>

(Default perms are 0644, i.e. rw-r--r-- for the numerically challenged.)

If you want to append to a file, for example, to add fortune to an already existing profile.d script.

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/stack-binaries.sh" mode="append" perms="0755">
fortune
</stack:file>
</stack:script>

(You can use all/some/none of those options.)

This will drop the file on the node on the path you've indicated.

Here's a realer (Yes, that's a word. I made it up. It's my word but you can use it.) example:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/security/limits.d/90-nproc.conf">
# Default limit for number of user's processes to prevent
# accidental fork bombs.
# See rhbz #432903 for reasoning.
* soft nproc 64000
</stack:file>
</stack:script>

Here is a more complicated example:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/security/limits.conf">
<![CDATA[
# /etc/security/limits.conf
#
#Each line describes a limit for a user in the form:
#
#<domain> <type> <item> <value>
#
#Where:
#<domain> can be:
# - an user name
# - a group name, with @group syntax
# - the wildcard *, for default entry
# - the wildcard %, can be also used with %group syntax,
# for maxlogin limit
#
#<type> can have the two values:
# - "soft" for enforcing the soft limits
# - "hard" for enforcing hard limits
#
#<item> can be one of the following:
# - core - limits the core file size (KB)
# - data - max data size (KB)
# - fsize - maximum filesize (KB)
# - memlock - max locked-in-memory address space (KB)
# - nofile - max number of open files
# - rss - max resident set size (KB)
# - stack - max stack size (KB)
# - cpu - max CPU time (MIN)
# - nproc - max number of processes
# - as - address space limit (KB)
# - maxlogins - max number of logins for this user
# - maxsyslogins - max number of logins on the system
# - priority - the priority to run user process with
# - locks - max number of file locks the user can hold
# - sigpending - max number of pending signals
# - msgqueue - max memory used by POSIX message queues (bytes)
# - nice - max nice priority allowed to raise to values: [-20, 19]
# - rtprio - max realtime priority
#
#<domain> <type> <item> <value>
#
#* soft core 0
#* hard rss 10000
#@student hard nproc 20
#@faculty soft nproc 20
#@faculty hard nproc 50
#ftp hard nproc 0
#@student - maxlogins 4
* soft nproc 64000
* hard nproc 64000
* soft nofile 65536
* hard nofile 65536
# End of file
mapr - memlock unlimited
mapr - core unlimited
mapr - nofile 32768
mapr - nproc unlimited
mapr - nice -10
mapr - renice -10
]]>
</stack:file>
</stack:script>

Note the "<![CDATA[ ]]>" construction. It allows you to run a script or create a config file with special characters (special to the XML parser anyway) without having to work out XML entity issues. Issues that can fubar your kickstart file. Use it if in doubt, and if you have scripts with redirection or init-style scripts, this is a valuable tool to have to use work you've done wholesale.

The CDATA contruction looks like this:

<stack:script stack:stage="install-post">
<![CDATA[
whole bunch of stuff I don't want to escape
]]>
</stack:script>

We did it for this file because in the comments you'll notice there are <domain>, <item>, and <type> comments. The brackets would otherwise need to be escaped in XML with &lt; or &gt;. But we're lazy because we're good system administrators so just throw it all into the CDATA construction.

We have touched on the surface of what can be done with files in Stacki UXML. Please see Stacki Universal XML for further details.

Adding scripts to enable start-up scripts and modify configuration can also be done during installation. Read Adding-Scripts for further detail.

Clone this wiki locally

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Adding Files

Joe Kaiser edited this page Jan 25, 2018 · 6 revisions

Adding Files

Whatever you can do in a shell, you can do during install.

Our assumption is that when a machine comes up, it should be exactly the way you want at first boot. This way you're certain your site specific customization is going to run once you hit the install/reinstall button, because you've already done the hard configuration scripting to make it so.

Which means you probably don't want to recreate all of that work just because you've started using a new tool. You've already figured it out, you don't want to do it again, and you probably can't remember why you do some of the things you do in those scripts. We'll discuss how to modify a cart to:

  • Not lose work you've already done.
  • Put your already existing config files where they belong: on the installing node.

site-custom cart example continued

In the Adding RPMS section, we started configuring an site-custom cart as an example -- we'll continue to use it here.

To properly have a fortune displayed when a user logs-in, you either have to put "fortune" in their .bashrc (untenable) or make it run automatically. Since /etc/profile.d has environment scripts, we'll put it there.

(Please note, the odds of you allowing users to login into the backends is probably not really a good idea, but for the sake of example, we are assuming this here.)

Go to the nodes directory of your cart:

# cd /export/stack/carts/site-custom/nodes

Edit cart-site-custom-backend.xml.

We are most concerned with what goes on between the:

<stack:script stack:stage="install-post"> </stack:script> tags.

This runs during the post-install configuration. It maps to the %post stanza in kickstart.

A <stack:file> tag must be placed between <stack:script> tags.

So in a script tag with the stage set to "install-post" we are going to add a file to the /etc/profile.d directory.

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh">
#!/bin/bash
fortune
</stack:file>
</stack:script>

This is the default structure for adding a file. If you don't set permissions, default is 644, default owner is root:root. You can set these options though, in the <stack:file> tag.

Other options

If you need to make it executable, you can set the permissions:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh" perms="0755">
#!/bin/bash
fortune
</stack:file>
</stack:script>

And, if you need to change owner/group:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh" owner="root:apache" perms="0755">
#!/bin/bash
fortune
</stack:file>
</stack:script>

(Default perms are 0644, i.e. rw-r--r-- for the numerically challenged.)

If you want to append to a file, for example, to add fortune to an already existing profile.d script.

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/stack-binaries.sh" mode="append" perms="0755">
fortune
</stack:file>
</stack:script>

(You can use all/some/none of those options.)

This will drop the file on the node on the path you've indicated.

Here's a realer (Yes, that's a word. I made it up. It's my word but you can use it.) example:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/security/limits.d/90-nproc.conf">
# Default limit for number of user's processes to prevent
# accidental fork bombs.
# See rhbz #432903 for reasoning.
* soft nproc 64000
</stack:file>
</stack:script>

Here is a more complicated example:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/security/limits.conf">
<![CDATA[
# /etc/security/limits.conf
#
#Each line describes a limit for a user in the form:
#
#<domain> <type> <item> <value>
#
#Where:
#<domain> can be:
# - an user name
# - a group name, with @group syntax
# - the wildcard *, for default entry
# - the wildcard %, can be also used with %group syntax,
# for maxlogin limit
#
#<type> can have the two values:
# - "soft" for enforcing the soft limits
# - "hard" for enforcing hard limits
#
#<item> can be one of the following:
# - core - limits the core file size (KB)
# - data - max data size (KB)
# - fsize - maximum filesize (KB)
# - memlock - max locked-in-memory address space (KB)
# - nofile - max number of open files
# - rss - max resident set size (KB)
# - stack - max stack size (KB)
# - cpu - max CPU time (MIN)
# - nproc - max number of processes
# - as - address space limit (KB)
# - maxlogins - max number of logins for this user
# - maxsyslogins - max number of logins on the system
# - priority - the priority to run user process with
# - locks - max number of file locks the user can hold
# - sigpending - max number of pending signals
# - msgqueue - max memory used by POSIX message queues (bytes)
# - nice - max nice priority allowed to raise to values: [-20, 19]
# - rtprio - max realtime priority
#
#<domain> <type> <item> <value>
#
#* soft core 0
#* hard rss 10000
#@student hard nproc 20
#@faculty soft nproc 20
#@faculty hard nproc 50
#ftp hard nproc 0
#@student - maxlogins 4
* soft nproc 64000
* hard nproc 64000
* soft nofile 65536
* hard nofile 65536
# End of file
mapr - memlock unlimited
mapr - core unlimited
mapr - nofile 32768
mapr - nproc unlimited
mapr - nice -10
mapr - renice -10
]]>
</stack:file>
</stack:script>

Note the "<![CDATA[ ]]>" construction. It allows you to run a script or create a config file with special characters (special to the XML parser anyway) without having to work out XML entity issues. Issues that can fubar your kickstart file. Use it if in doubt, and if you have scripts with redirection or init-style scripts, this is a valuable tool to have to use work you've done wholesale.

The CDATA contruction looks like this:

<stack:script stack:stage="install-post">
<![CDATA[
whole bunch of stuff I don't want to escape
]]>
</stack:script>

We did it for this file because in the comments you'll notice there are <domain>, <item>, and <type> comments. The brackets would otherwise need to be escaped in XML with &lt; or &gt;. But we're lazy because we're good system administrators so just throw it all into the CDATA construction.

We have touched on the surface of what can be done with files in Stacki UXML. Please see Stacki Universal XML for further details.

Adding scripts to enable start-up scripts and modify configuration can also be done during installation. Read Adding-Scripts for further detail.

Clone this wiki locally

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Adding Files

Joe Kaiser edited this page Jan 25, 2018 · 6 revisions

Adding Files

Whatever you can do in a shell, you can do during install.

Our assumption is that when a machine comes up, it should be exactly the way you want at first boot. This way you're certain your site specific customization is going to run once you hit the install/reinstall button, because you've already done the hard configuration scripting to make it so.

Which means you probably don't want to recreate all of that work just because you've started using a new tool. You've already figured it out, you don't want to do it again, and you probably can't remember why you do some of the things you do in those scripts. We'll discuss how to modify a cart to:

  • Not lose work you've already done.
  • Put your already existing config files where they belong: on the installing node.

site-custom cart example continued

In the Adding RPMS section, we started configuring an site-custom cart as an example -- we'll continue to use it here.

To properly have a fortune displayed when a user logs-in, you either have to put "fortune" in their .bashrc (untenable) or make it run automatically. Since /etc/profile.d has environment scripts, we'll put it there.

(Please note, the odds of you allowing users to login into the backends is probably not really a good idea, but for the sake of example, we are assuming this here.)

Go to the nodes directory of your cart:

# cd /export/stack/carts/site-custom/nodes

Edit cart-site-custom-backend.xml.

We are most concerned with what goes on between the:

<stack:script stack:stage="install-post"> </stack:script> tags.

This runs during the post-install configuration. It maps to the %post stanza in kickstart.

A <stack:file> tag must be placed between <stack:script> tags.

So in a script tag with the stage set to "install-post" we are going to add a file to the /etc/profile.d directory.

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh">
#!/bin/bash
fortune
</stack:file>
</stack:script>

This is the default structure for adding a file. If you don't set permissions, default is 644, default owner is root:root. You can set these options though, in the <stack:file> tag.

Other options

If you need to make it executable, you can set the permissions:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh" perms="0755">
#!/bin/bash
fortune
</stack:file>
</stack:script>

And, if you need to change owner/group:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh" owner="root:apache" perms="0755">
#!/bin/bash
fortune
</stack:file>
</stack:script>

(Default perms are 0644, i.e. rw-r--r-- for the numerically challenged.)

If you want to append to a file, for example, to add fortune to an already existing profile.d script.

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/stack-binaries.sh" mode="append" perms="0755">
fortune
</stack:file>
</stack:script>

(You can use all/some/none of those options.)

This will drop the file on the node on the path you've indicated.

Here's a realer (Yes, that's a word. I made it up. It's my word but you can use it.) example:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/security/limits.d/90-nproc.conf">
# Default limit for number of user's processes to prevent
# accidental fork bombs.
# See rhbz #432903 for reasoning.
* soft nproc 64000
</stack:file>
</stack:script>

Here is a more complicated example:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/security/limits.conf">
<![CDATA[
# /etc/security/limits.conf
#
#Each line describes a limit for a user in the form:
#
#<domain> <type> <item> <value>
#
#Where:
#<domain> can be:
# - an user name
# - a group name, with @group syntax
# - the wildcard *, for default entry
# - the wildcard %, can be also used with %group syntax,
# for maxlogin limit
#
#<type> can have the two values:
# - "soft" for enforcing the soft limits
# - "hard" for enforcing hard limits
#
#<item> can be one of the following:
# - core - limits the core file size (KB)
# - data - max data size (KB)
# - fsize - maximum filesize (KB)
# - memlock - max locked-in-memory address space (KB)
# - nofile - max number of open files
# - rss - max resident set size (KB)
# - stack - max stack size (KB)
# - cpu - max CPU time (MIN)
# - nproc - max number of processes
# - as - address space limit (KB)
# - maxlogins - max number of logins for this user
# - maxsyslogins - max number of logins on the system
# - priority - the priority to run user process with
# - locks - max number of file locks the user can hold
# - sigpending - max number of pending signals
# - msgqueue - max memory used by POSIX message queues (bytes)
# - nice - max nice priority allowed to raise to values: [-20, 19]
# - rtprio - max realtime priority
#
#<domain> <type> <item> <value>
#
#* soft core 0
#* hard rss 10000
#@student hard nproc 20
#@faculty soft nproc 20
#@faculty hard nproc 50
#ftp hard nproc 0
#@student - maxlogins 4
* soft nproc 64000
* hard nproc 64000
* soft nofile 65536
* hard nofile 65536
# End of file
mapr - memlock unlimited
mapr - core unlimited
mapr - nofile 32768
mapr - nproc unlimited
mapr - nice -10
mapr - renice -10
]]>
</stack:file>
</stack:script>

Note the "<![CDATA[ ]]>" construction. It allows you to run a script or create a config file with special characters (special to the XML parser anyway) without having to work out XML entity issues. Issues that can fubar your kickstart file. Use it if in doubt, and if you have scripts with redirection or init-style scripts, this is a valuable tool to have to use work you've done wholesale.

The CDATA contruction looks like this:

<stack:script stack:stage="install-post">
<![CDATA[
whole bunch of stuff I don't want to escape
]]>
</stack:script>

We did it for this file because in the comments you'll notice there are <domain>, <item>, and <type> comments. The brackets would otherwise need to be escaped in XML with &lt; or &gt;. But we're lazy because we're good system administrators so just throw it all into the CDATA construction.

We have touched on the surface of what can be done with files in Stacki UXML. Please see Stacki Universal XML for further details.

Adding scripts to enable start-up scripts and modify configuration can also be done during installation. Read Adding-Scripts for further detail.

Clone this wiki locally

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Adding Files

Joe Kaiser edited this page Jan 25, 2018 · 6 revisions

Adding Files

Whatever you can do in a shell, you can do during install.

Our assumption is that when a machine comes up, it should be exactly the way you want at first boot. This way you're certain your site specific customization is going to run once you hit the install/reinstall button, because you've already done the hard configuration scripting to make it so.

Which means you probably don't want to recreate all of that work just because you've started using a new tool. You've already figured it out, you don't want to do it again, and you probably can't remember why you do some of the things you do in those scripts. We'll discuss how to modify a cart to:

  • Not lose work you've already done.
  • Put your already existing config files where they belong: on the installing node.

site-custom cart example continued

In the Adding RPMS section, we started configuring an site-custom cart as an example -- we'll continue to use it here.

To properly have a fortune displayed when a user logs-in, you either have to put "fortune" in their .bashrc (untenable) or make it run automatically. Since /etc/profile.d has environment scripts, we'll put it there.

(Please note, the odds of you allowing users to login into the backends is probably not really a good idea, but for the sake of example, we are assuming this here.)

Go to the nodes directory of your cart:

# cd /export/stack/carts/site-custom/nodes

Edit cart-site-custom-backend.xml.

We are most concerned with what goes on between the:

<stack:script stack:stage="install-post"> </stack:script> tags.

This runs during the post-install configuration. It maps to the %post stanza in kickstart.

A <stack:file> tag must be placed between <stack:script> tags.

So in a script tag with the stage set to "install-post" we are going to add a file to the /etc/profile.d directory.

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh">
#!/bin/bash
fortune
</stack:file>
</stack:script>

This is the default structure for adding a file. If you don't set permissions, default is 644, default owner is root:root. You can set these options though, in the <stack:file> tag.

Other options

If you need to make it executable, you can set the permissions:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh" perms="0755">
#!/bin/bash
fortune
</stack:file>
</stack:script>

And, if you need to change owner/group:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh" owner="root:apache" perms="0755">
#!/bin/bash
fortune
</stack:file>
</stack:script>

(Default perms are 0644, i.e. rw-r--r-- for the numerically challenged.)

If you want to append to a file, for example, to add fortune to an already existing profile.d script.

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/stack-binaries.sh" mode="append" perms="0755">
fortune
</stack:file>
</stack:script>

(You can use all/some/none of those options.)

This will drop the file on the node on the path you've indicated.

Here's a realer (Yes, that's a word. I made it up. It's my word but you can use it.) example:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/security/limits.d/90-nproc.conf">
# Default limit for number of user's processes to prevent
# accidental fork bombs.
# See rhbz #432903 for reasoning.
* soft nproc 64000
</stack:file>
</stack:script>

Here is a more complicated example:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/security/limits.conf">
<![CDATA[
# /etc/security/limits.conf
#
#Each line describes a limit for a user in the form:
#
#<domain> <type> <item> <value>
#
#Where:
#<domain> can be:
# - an user name
# - a group name, with @group syntax
# - the wildcard *, for default entry
# - the wildcard %, can be also used with %group syntax,
# for maxlogin limit
#
#<type> can have the two values:
# - "soft" for enforcing the soft limits
# - "hard" for enforcing hard limits
#
#<item> can be one of the following:
# - core - limits the core file size (KB)
# - data - max data size (KB)
# - fsize - maximum filesize (KB)
# - memlock - max locked-in-memory address space (KB)
# - nofile - max number of open files
# - rss - max resident set size (KB)
# - stack - max stack size (KB)
# - cpu - max CPU time (MIN)
# - nproc - max number of processes
# - as - address space limit (KB)
# - maxlogins - max number of logins for this user
# - maxsyslogins - max number of logins on the system
# - priority - the priority to run user process with
# - locks - max number of file locks the user can hold
# - sigpending - max number of pending signals
# - msgqueue - max memory used by POSIX message queues (bytes)
# - nice - max nice priority allowed to raise to values: [-20, 19]
# - rtprio - max realtime priority
#
#<domain> <type> <item> <value>
#
#* soft core 0
#* hard rss 10000
#@student hard nproc 20
#@faculty soft nproc 20
#@faculty hard nproc 50
#ftp hard nproc 0
#@student - maxlogins 4
* soft nproc 64000
* hard nproc 64000
* soft nofile 65536
* hard nofile 65536
# End of file
mapr - memlock unlimited
mapr - core unlimited
mapr - nofile 32768
mapr - nproc unlimited
mapr - nice -10
mapr - renice -10
]]>
</stack:file>
</stack:script>

Note the "<![CDATA[ ]]>" construction. It allows you to run a script or create a config file with special characters (special to the XML parser anyway) without having to work out XML entity issues. Issues that can fubar your kickstart file. Use it if in doubt, and if you have scripts with redirection or init-style scripts, this is a valuable tool to have to use work you've done wholesale.

The CDATA contruction looks like this:

<stack:script stack:stage="install-post">
<![CDATA[
whole bunch of stuff I don't want to escape
]]>
</stack:script>

We did it for this file because in the comments you'll notice there are <domain>, <item>, and <type> comments. The brackets would otherwise need to be escaped in XML with &lt; or &gt;. But we're lazy because we're good system administrators so just throw it all into the CDATA construction.

We have touched on the surface of what can be done with files in Stacki UXML. Please see Stacki Universal XML for further details.

Adding scripts to enable start-up scripts and modify configuration can also be done during installation. Read Adding-Scripts for further detail.

Clone this wiki locally

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Adding Files

Joe Kaiser edited this page Jan 25, 2018 · 6 revisions

Adding Files

Whatever you can do in a shell, you can do during install.

Our assumption is that when a machine comes up, it should be exactly the way you want at first boot. This way you're certain your site specific customization is going to run once you hit the install/reinstall button, because you've already done the hard configuration scripting to make it so.

Which means you probably don't want to recreate all of that work just because you've started using a new tool. You've already figured it out, you don't want to do it again, and you probably can't remember why you do some of the things you do in those scripts. We'll discuss how to modify a cart to:

  • Not lose work you've already done.
  • Put your already existing config files where they belong: on the installing node.

site-custom cart example continued

In the Adding RPMS section, we started configuring an site-custom cart as an example -- we'll continue to use it here.

To properly have a fortune displayed when a user logs-in, you either have to put "fortune" in their .bashrc (untenable) or make it run automatically. Since /etc/profile.d has environment scripts, we'll put it there.

(Please note, the odds of you allowing users to login into the backends is probably not really a good idea, but for the sake of example, we are assuming this here.)

Go to the nodes directory of your cart:

# cd /export/stack/carts/site-custom/nodes

Edit cart-site-custom-backend.xml.

We are most concerned with what goes on between the:

<stack:script stack:stage="install-post"> </stack:script> tags.

This runs during the post-install configuration. It maps to the %post stanza in kickstart.

A <stack:file> tag must be placed between <stack:script> tags.

So in a script tag with the stage set to "install-post" we are going to add a file to the /etc/profile.d directory.

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh">
#!/bin/bash
fortune
</stack:file>
</stack:script>

This is the default structure for adding a file. If you don't set permissions, default is 644, default owner is root:root. You can set these options though, in the <stack:file> tag.

Other options

If you need to make it executable, you can set the permissions:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh" perms="0755">
#!/bin/bash
fortune
</stack:file>
</stack:script>

And, if you need to change owner/group:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh" owner="root:apache" perms="0755">
#!/bin/bash
fortune
</stack:file>
</stack:script>

(Default perms are 0644, i.e. rw-r--r-- for the numerically challenged.)

If you want to append to a file, for example, to add fortune to an already existing profile.d script.

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/stack-binaries.sh" mode="append" perms="0755">
fortune
</stack:file>
</stack:script>

(You can use all/some/none of those options.)

This will drop the file on the node on the path you've indicated.

Here's a realer (Yes, that's a word. I made it up. It's my word but you can use it.) example:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/security/limits.d/90-nproc.conf">
# Default limit for number of user's processes to prevent
# accidental fork bombs.
# See rhbz #432903 for reasoning.
* soft nproc 64000
</stack:file>
</stack:script>

Here is a more complicated example:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/security/limits.conf">
<![CDATA[
# /etc/security/limits.conf
#
#Each line describes a limit for a user in the form:
#
#<domain> <type> <item> <value>
#
#Where:
#<domain> can be:
# - an user name
# - a group name, with @group syntax
# - the wildcard *, for default entry
# - the wildcard %, can be also used with %group syntax,
# for maxlogin limit
#
#<type> can have the two values:
# - "soft" for enforcing the soft limits
# - "hard" for enforcing hard limits
#
#<item> can be one of the following:
# - core - limits the core file size (KB)
# - data - max data size (KB)
# - fsize - maximum filesize (KB)
# - memlock - max locked-in-memory address space (KB)
# - nofile - max number of open files
# - rss - max resident set size (KB)
# - stack - max stack size (KB)
# - cpu - max CPU time (MIN)
# - nproc - max number of processes
# - as - address space limit (KB)
# - maxlogins - max number of logins for this user
# - maxsyslogins - max number of logins on the system
# - priority - the priority to run user process with
# - locks - max number of file locks the user can hold
# - sigpending - max number of pending signals
# - msgqueue - max memory used by POSIX message queues (bytes)
# - nice - max nice priority allowed to raise to values: [-20, 19]
# - rtprio - max realtime priority
#
#<domain> <type> <item> <value>
#
#* soft core 0
#* hard rss 10000
#@student hard nproc 20
#@faculty soft nproc 20
#@faculty hard nproc 50
#ftp hard nproc 0
#@student - maxlogins 4
* soft nproc 64000
* hard nproc 64000
* soft nofile 65536
* hard nofile 65536
# End of file
mapr - memlock unlimited
mapr - core unlimited
mapr - nofile 32768
mapr - nproc unlimited
mapr - nice -10
mapr - renice -10
]]>
</stack:file>
</stack:script>

Note the "<![CDATA[ ]]>" construction. It allows you to run a script or create a config file with special characters (special to the XML parser anyway) without having to work out XML entity issues. Issues that can fubar your kickstart file. Use it if in doubt, and if you have scripts with redirection or init-style scripts, this is a valuable tool to have to use work you've done wholesale.

The CDATA contruction looks like this:

<stack:script stack:stage="install-post">
<![CDATA[
whole bunch of stuff I don't want to escape
]]>
</stack:script>

We did it for this file because in the comments you'll notice there are <domain>, <item>, and <type> comments. The brackets would otherwise need to be escaped in XML with &lt; or &gt;. But we're lazy because we're good system administrators so just throw it all into the CDATA construction.

We have touched on the surface of what can be done with files in Stacki UXML. Please see Stacki Universal XML for further details.

Adding scripts to enable start-up scripts and modify configuration can also be done during installation. Read Adding-Scripts for further detail.

Clone this wiki locally

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Adding Files

Joe Kaiser edited this page Jan 25, 2018 · 6 revisions

Adding Files

Whatever you can do in a shell, you can do during install.

Our assumption is that when a machine comes up, it should be exactly the way you want at first boot. This way you're certain your site specific customization is going to run once you hit the install/reinstall button, because you've already done the hard configuration scripting to make it so.

Which means you probably don't want to recreate all of that work just because you've started using a new tool. You've already figured it out, you don't want to do it again, and you probably can't remember why you do some of the things you do in those scripts. We'll discuss how to modify a cart to:

  • Not lose work you've already done.
  • Put your already existing config files where they belong: on the installing node.

site-custom cart example continued

In the Adding RPMS section, we started configuring an site-custom cart as an example -- we'll continue to use it here.

To properly have a fortune displayed when a user logs-in, you either have to put "fortune" in their .bashrc (untenable) or make it run automatically. Since /etc/profile.d has environment scripts, we'll put it there.

(Please note, the odds of you allowing users to login into the backends is probably not really a good idea, but for the sake of example, we are assuming this here.)

Go to the nodes directory of your cart:

# cd /export/stack/carts/site-custom/nodes

Edit cart-site-custom-backend.xml.

We are most concerned with what goes on between the:

<stack:script stack:stage="install-post"> </stack:script> tags.

This runs during the post-install configuration. It maps to the %post stanza in kickstart.

A <stack:file> tag must be placed between <stack:script> tags.

So in a script tag with the stage set to "install-post" we are going to add a file to the /etc/profile.d directory.

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh">
#!/bin/bash
fortune
</stack:file>
</stack:script>

This is the default structure for adding a file. If you don't set permissions, default is 644, default owner is root:root. You can set these options though, in the <stack:file> tag.

Other options

If you need to make it executable, you can set the permissions:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh" perms="0755">
#!/bin/bash
fortune
</stack:file>
</stack:script>

And, if you need to change owner/group:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh" owner="root:apache" perms="0755">
#!/bin/bash
fortune
</stack:file>
</stack:script>

(Default perms are 0644, i.e. rw-r--r-- for the numerically challenged.)

If you want to append to a file, for example, to add fortune to an already existing profile.d script.

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/stack-binaries.sh" mode="append" perms="0755">
fortune
</stack:file>
</stack:script>

(You can use all/some/none of those options.)

This will drop the file on the node on the path you've indicated.

Here's a realer (Yes, that's a word. I made it up. It's my word but you can use it.) example:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/security/limits.d/90-nproc.conf">
# Default limit for number of user's processes to prevent
# accidental fork bombs.
# See rhbz #432903 for reasoning.
* soft nproc 64000
</stack:file>
</stack:script>

Here is a more complicated example:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/security/limits.conf">
<![CDATA[
# /etc/security/limits.conf
#
#Each line describes a limit for a user in the form:
#
#<domain> <type> <item> <value>
#
#Where:
#<domain> can be:
# - an user name
# - a group name, with @group syntax
# - the wildcard *, for default entry
# - the wildcard %, can be also used with %group syntax,
# for maxlogin limit
#
#<type> can have the two values:
# - "soft" for enforcing the soft limits
# - "hard" for enforcing hard limits
#
#<item> can be one of the following:
# - core - limits the core file size (KB)
# - data - max data size (KB)
# - fsize - maximum filesize (KB)
# - memlock - max locked-in-memory address space (KB)
# - nofile - max number of open files
# - rss - max resident set size (KB)
# - stack - max stack size (KB)
# - cpu - max CPU time (MIN)
# - nproc - max number of processes
# - as - address space limit (KB)
# - maxlogins - max number of logins for this user
# - maxsyslogins - max number of logins on the system
# - priority - the priority to run user process with
# - locks - max number of file locks the user can hold
# - sigpending - max number of pending signals
# - msgqueue - max memory used by POSIX message queues (bytes)
# - nice - max nice priority allowed to raise to values: [-20, 19]
# - rtprio - max realtime priority
#
#<domain> <type> <item> <value>
#
#* soft core 0
#* hard rss 10000
#@student hard nproc 20
#@faculty soft nproc 20
#@faculty hard nproc 50
#ftp hard nproc 0
#@student - maxlogins 4
* soft nproc 64000
* hard nproc 64000
* soft nofile 65536
* hard nofile 65536
# End of file
mapr - memlock unlimited
mapr - core unlimited
mapr - nofile 32768
mapr - nproc unlimited
mapr - nice -10
mapr - renice -10
]]>
</stack:file>
</stack:script>

Note the "<![CDATA[ ]]>" construction. It allows you to run a script or create a config file with special characters (special to the XML parser anyway) without having to work out XML entity issues. Issues that can fubar your kickstart file. Use it if in doubt, and if you have scripts with redirection or init-style scripts, this is a valuable tool to have to use work you've done wholesale.

The CDATA contruction looks like this:

<stack:script stack:stage="install-post">
<![CDATA[
whole bunch of stuff I don't want to escape
]]>
</stack:script>

We did it for this file because in the comments you'll notice there are <domain>, <item>, and <type> comments. The brackets would otherwise need to be escaped in XML with &lt; or &gt;. But we're lazy because we're good system administrators so just throw it all into the CDATA construction.

We have touched on the surface of what can be done with files in Stacki UXML. Please see Stacki Universal XML for further details.

Adding scripts to enable start-up scripts and modify configuration can also be done during installation. Read Adding-Scripts for further detail.

Clone this wiki locally

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Adding Files

Joe Kaiser edited this page Jan 25, 2018 · 6 revisions

Adding Files

Whatever you can do in a shell, you can do during install.

Our assumption is that when a machine comes up, it should be exactly the way you want at first boot. This way you're certain your site specific customization is going to run once you hit the install/reinstall button, because you've already done the hard configuration scripting to make it so.

Which means you probably don't want to recreate all of that work just because you've started using a new tool. You've already figured it out, you don't want to do it again, and you probably can't remember why you do some of the things you do in those scripts. We'll discuss how to modify a cart to:

  • Not lose work you've already done.
  • Put your already existing config files where they belong: on the installing node.

site-custom cart example continued

In the Adding RPMS section, we started configuring an site-custom cart as an example -- we'll continue to use it here.

To properly have a fortune displayed when a user logs-in, you either have to put "fortune" in their .bashrc (untenable) or make it run automatically. Since /etc/profile.d has environment scripts, we'll put it there.

(Please note, the odds of you allowing users to login into the backends is probably not really a good idea, but for the sake of example, we are assuming this here.)

Go to the nodes directory of your cart:

# cd /export/stack/carts/site-custom/nodes

Edit cart-site-custom-backend.xml.

We are most concerned with what goes on between the:

<stack:script stack:stage="install-post"> </stack:script> tags.

This runs during the post-install configuration. It maps to the %post stanza in kickstart.

A <stack:file> tag must be placed between <stack:script> tags.

So in a script tag with the stage set to "install-post" we are going to add a file to the /etc/profile.d directory.

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh">
#!/bin/bash
fortune
</stack:file>
</stack:script>

This is the default structure for adding a file. If you don't set permissions, default is 644, default owner is root:root. You can set these options though, in the <stack:file> tag.

Other options

If you need to make it executable, you can set the permissions:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh" perms="0755">
#!/bin/bash
fortune
</stack:file>
</stack:script>

And, if you need to change owner/group:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh" owner="root:apache" perms="0755">
#!/bin/bash
fortune
</stack:file>
</stack:script>

(Default perms are 0644, i.e. rw-r--r-- for the numerically challenged.)

If you want to append to a file, for example, to add fortune to an already existing profile.d script.

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/stack-binaries.sh" mode="append" perms="0755">
fortune
</stack:file>
</stack:script>

(You can use all/some/none of those options.)

This will drop the file on the node on the path you've indicated.

Here's a realer (Yes, that's a word. I made it up. It's my word but you can use it.) example:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/security/limits.d/90-nproc.conf">
# Default limit for number of user's processes to prevent
# accidental fork bombs.
# See rhbz #432903 for reasoning.
* soft nproc 64000
</stack:file>
</stack:script>

Here is a more complicated example:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/security/limits.conf">
<![CDATA[
# /etc/security/limits.conf
#
#Each line describes a limit for a user in the form:
#
#<domain> <type> <item> <value>
#
#Where:
#<domain> can be:
# - an user name
# - a group name, with @group syntax
# - the wildcard *, for default entry
# - the wildcard %, can be also used with %group syntax,
# for maxlogin limit
#
#<type> can have the two values:
# - "soft" for enforcing the soft limits
# - "hard" for enforcing hard limits
#
#<item> can be one of the following:
# - core - limits the core file size (KB)
# - data - max data size (KB)
# - fsize - maximum filesize (KB)
# - memlock - max locked-in-memory address space (KB)
# - nofile - max number of open files
# - rss - max resident set size (KB)
# - stack - max stack size (KB)
# - cpu - max CPU time (MIN)
# - nproc - max number of processes
# - as - address space limit (KB)
# - maxlogins - max number of logins for this user
# - maxsyslogins - max number of logins on the system
# - priority - the priority to run user process with
# - locks - max number of file locks the user can hold
# - sigpending - max number of pending signals
# - msgqueue - max memory used by POSIX message queues (bytes)
# - nice - max nice priority allowed to raise to values: [-20, 19]
# - rtprio - max realtime priority
#
#<domain> <type> <item> <value>
#
#* soft core 0
#* hard rss 10000
#@student hard nproc 20
#@faculty soft nproc 20
#@faculty hard nproc 50
#ftp hard nproc 0
#@student - maxlogins 4
* soft nproc 64000
* hard nproc 64000
* soft nofile 65536
* hard nofile 65536
# End of file
mapr - memlock unlimited
mapr - core unlimited
mapr - nofile 32768
mapr - nproc unlimited
mapr - nice -10
mapr - renice -10
]]>
</stack:file>
</stack:script>

Note the "<![CDATA[ ]]>" construction. It allows you to run a script or create a config file with special characters (special to the XML parser anyway) without having to work out XML entity issues. Issues that can fubar your kickstart file. Use it if in doubt, and if you have scripts with redirection or init-style scripts, this is a valuable tool to have to use work you've done wholesale.

The CDATA contruction looks like this:

<stack:script stack:stage="install-post">
<![CDATA[
whole bunch of stuff I don't want to escape
]]>
</stack:script>

We did it for this file because in the comments you'll notice there are <domain>, <item>, and <type> comments. The brackets would otherwise need to be escaped in XML with &lt; or &gt;. But we're lazy because we're good system administrators so just throw it all into the CDATA construction.

We have touched on the surface of what can be done with files in Stacki UXML. Please see Stacki Universal XML for further details.

Adding scripts to enable start-up scripts and modify configuration can also be done during installation. Read Adding-Scripts for further detail.

Clone this wiki locally

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Adding Files

Joe Kaiser edited this page Jan 25, 2018 · 6 revisions

Adding Files

Whatever you can do in a shell, you can do during install.

Our assumption is that when a machine comes up, it should be exactly the way you want at first boot. This way you're certain your site specific customization is going to run once you hit the install/reinstall button, because you've already done the hard configuration scripting to make it so.

Which means you probably don't want to recreate all of that work just because you've started using a new tool. You've already figured it out, you don't want to do it again, and you probably can't remember why you do some of the things you do in those scripts. We'll discuss how to modify a cart to:

  • Not lose work you've already done.
  • Put your already existing config files where they belong: on the installing node.

site-custom cart example continued

In the Adding RPMS section, we started configuring an site-custom cart as an example -- we'll continue to use it here.

To properly have a fortune displayed when a user logs-in, you either have to put "fortune" in their .bashrc (untenable) or make it run automatically. Since /etc/profile.d has environment scripts, we'll put it there.

(Please note, the odds of you allowing users to login into the backends is probably not really a good idea, but for the sake of example, we are assuming this here.)

Go to the nodes directory of your cart:

# cd /export/stack/carts/site-custom/nodes

Edit cart-site-custom-backend.xml.

We are most concerned with what goes on between the:

<stack:script stack:stage="install-post"> </stack:script> tags.

This runs during the post-install configuration. It maps to the %post stanza in kickstart.

A <stack:file> tag must be placed between <stack:script> tags.

So in a script tag with the stage set to "install-post" we are going to add a file to the /etc/profile.d directory.

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh">
#!/bin/bash
fortune
</stack:file>
</stack:script>

This is the default structure for adding a file. If you don't set permissions, default is 644, default owner is root:root. You can set these options though, in the <stack:file> tag.

Other options

If you need to make it executable, you can set the permissions:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh" perms="0755">
#!/bin/bash
fortune
</stack:file>
</stack:script>

And, if you need to change owner/group:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/fortune.sh" owner="root:apache" perms="0755">
#!/bin/bash
fortune
</stack:file>
</stack:script>

(Default perms are 0644, i.e. rw-r--r-- for the numerically challenged.)

If you want to append to a file, for example, to add fortune to an already existing profile.d script.

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/profile.d/stack-binaries.sh" mode="append" perms="0755">
fortune
</stack:file>
</stack:script>

(You can use all/some/none of those options.)

This will drop the file on the node on the path you've indicated.

Here's a realer (Yes, that's a word. I made it up. It's my word but you can use it.) example:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/security/limits.d/90-nproc.conf">
# Default limit for number of user's processes to prevent
# accidental fork bombs.
# See rhbz #432903 for reasoning.
* soft nproc 64000
</stack:file>
</stack:script>

Here is a more complicated example:

<stack:script stack:stage="install-post">
<stack:file stack:name="/etc/security/limits.conf">
<![CDATA[
# /etc/security/limits.conf
#
#Each line describes a limit for a user in the form:
#
#<domain> <type> <item> <value>
#
#Where:
#<domain> can be:
# - an user name
# - a group name, with @group syntax
# - the wildcard *, for default entry
# - the wildcard %, can be also used with %group syntax,
# for maxlogin limit
#
#<type> can have the two values:
# - "soft" for enforcing the soft limits
# - "hard" for enforcing hard limits
#
#<item> can be one of the following:
# - core - limits the core file size (KB)
# - data - max data size (KB)
# - fsize - maximum filesize (KB)
# - memlock - max locked-in-memory address space (KB)
# - nofile - max number of open files
# - rss - max resident set size (KB)
# - stack - max stack size (KB)
# - cpu - max CPU time (MIN)
# - nproc - max number of processes
# - as - address space limit (KB)
# - maxlogins - max number of logins for this user
# - maxsyslogins - max number of logins on the system
# - priority - the priority to run user process with
# - locks - max number of file locks the user can hold
# - sigpending - max number of pending signals
# - msgqueue - max memory used by POSIX message queues (bytes)
# - nice - max nice priority allowed to raise to values: [-20, 19]
# - rtprio - max realtime priority
#
#<domain> <type> <item> <value>
#
#* soft core 0
#* hard rss 10000
#@student hard nproc 20
#@faculty soft nproc 20
#@faculty hard nproc 50
#ftp hard nproc 0
#@student - maxlogins 4
* soft nproc 64000
* hard nproc 64000
* soft nofile 65536
* hard nofile 65536
# End of file
mapr - memlock unlimited
mapr - core unlimited
mapr - nofile 32768
mapr - nproc unlimited
mapr - nice -10
mapr - renice -10
]]>
</stack:file>
</stack:script>

Note the "<![CDATA[ ]]>" construction. It allows you to run a script or create a config file with special characters (special to the XML parser anyway) without having to work out XML entity issues. Issues that can fubar your kickstart file. Use it if in doubt, and if you have scripts with redirection or init-style scripts, this is a valuable tool to have to use work you've done wholesale.

The CDATA contruction looks like this:

<stack:script stack:stage="install-post">
<![CDATA[
whole bunch of stuff I don't want to escape
]]>
</stack:script>

We did it for this file because in the comments you'll notice there are <domain>, <item>, and <type> comments. The brackets would otherwise need to be escaped in XML with &lt; or &gt;. But we're lazy because we're good system administrators so just throw it all into the CDATA construction.

We have touched on the surface of what can be done with files in Stacki UXML. Please see Stacki Universal XML for further details.

Adding scripts to enable start-up scripts and modify configuration can also be done during installation. Read Adding-Scripts for further detail.

Clone this wiki locally