commit
346a50856b
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,76 @@
|
||||
# Hestia Control Panel - Contribution Guidelines
|
||||
|
||||
## Ways to contribute
|
||||
|
||||
- **Beta testing**:
|
||||
- Download and install builds from the `beta` branch. If you encounter an issue with a beta build, file an issue report on [GitHub](https://www.github.com/hestiacp/hestiacp/issues).<br>
|
||||
`v-update-sys-hestia-git hestiacp beta install` will install the latest beta build from our GitHub repository.
|
||||
- **Code review and bug fixes**:
|
||||
- Read over the code and if you notice errors (even spelling mistakes), submit a pull request with your changes.
|
||||
- **New features**:
|
||||
- Is there an awesome feature that you'd love to see included? Submit a pull request with your changes, and if approved your PR will be reviewed and merged for inclusion in an upcoming release. While our development team tries to accommodate all reasonable requests please remember that it does take time to develop, implement and test new features and as such we may not be able to fulfill all requests or may have to put a feature on backlog for a later date.
|
||||
- **Translations**:
|
||||
- If you are a non-English speaker and would like to improve the quality of the translations used in Hestia Control Panel's web interface, please go to [Hestia Translate](https://translate.hestiacp.com/projects/hestiacp/) to review the translations database. For more information please read [How to contribute with Translations](https://forum.hestiacp.com/t/how-to-contribute-with-translations/1664) on our forum. You can also open an issue report [GitHub](https://www.github.com/hestiacp/hestiacp/issues) highlighting the issue with the current translation so that it can be corrected.
|
||||
- **Donations**:
|
||||
- If you're not a developer but you still want to make a contribution to support Hestia Control Panel and our developers, you can make a donation to the Hestia Control Panel project to further its development (or if you'd just like to buy our developers a lunch, we'd appreciate that too). We currently accept donations through [PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ST87LQH2CHGLA).
|
||||
|
||||
## Development Guidelines
|
||||
|
||||
Additional information on how to contribute to Hestia Control Panel can be found in the [Development](docs/docs/contributing/development.md) documentation.
|
||||
|
||||
### Code formatting and comments
|
||||
|
||||
We ask that you follow existing naming schemes and coding conventions where possible, and that you add comments in your source code where appropriate to aid other developers in debugging and understanding your code in the future.
|
||||
|
||||
To ensure your changes meet our formatting requirements, please run `npm install` from the root of the repository before committing your changes. This will set up pre-commit hooks for automatic formatting, which will help to get your changes merged as quickly as possible.
|
||||
|
||||
### Workflow and process
|
||||
|
||||
Development for this project takes place in branches to effectively develop, manage, and test new features and code changes. Our tiered approach allows us to closely control the quality of code as it is checked in for inclusion.
|
||||
|
||||
We have three primary or "evergreen" branches, which exist throughout our product's lifetime. Please refer to the following table for a description:
|
||||
|
||||
| Branch | Description |
|
||||
| --------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------: |
|
||||
| `main` | Contains a snapshot of the latest development code.<br>**Not intended for production use and contains code from a merge snapshot.** |
|
||||
| `beta` | Contains a snapshot of the next version which is currently in testing.<br>**Not intended for production use, however code from this branch should be stable.** |
|
||||
| `release` | Contains a snapshot of the latest stable release.<br>**Intended for production use. This repository contains the same code as our compiled packages.** |
|
||||
|
||||
### Creating a new branch and submitting pull requests
|
||||
|
||||
The first step is to create a fork of the `hestiacp/hestiacp` repository under your GitHub account so that you may submit pull requests and patches.
|
||||
|
||||
Once you've created your fork, clone the repository to your computer and make sure that you've checked out the `main` branch. **Always** create a new topic branch for your work.
|
||||
|
||||
### Branch naming convention
|
||||
|
||||
- **Prefix:** `topic/` (such as **fix**, **feature**, **refactor**, etc.)
|
||||
- **ID**: `888` (GitHub Issue ID if an issue exists)
|
||||
- **Title:** `my-awesome-patch`
|
||||
|
||||
Branch name examples:
|
||||
|
||||
- `feature/777-my-awesome-new-feature` or `feature/my-other-new-feature`
|
||||
- `fix/000-some-bug-fix` or `fix/this-feature-is-broken`
|
||||
- `refactor/v-change-domain-owner`
|
||||
- `test/mail-domain-ssl`
|
||||
|
||||
### Squashing commits for smaller changes
|
||||
|
||||
To aid other developers and keep the project's commit history clean, please **squash your commits** when it's appropriate. For example with smaller commits related to the same piece of code, such as commits labelled "Fixed item 1", "Adjusted color of button XYZ", "Adjusted alignment of button XYZ" can be squashed into one commit with the title "Fixed button issues in item".
|
||||
|
||||
### What happens when I submit a pull request?
|
||||
|
||||
- Our internal development team will review your work and validate your request.
|
||||
- Your changes will be tested to ensure that there are no issues.
|
||||
- If changes need to be made, you will be notified via GitHub.
|
||||
- Once approved, your code will be merged for inclusion in an upcoming release of Hestia Control Panel.
|
||||
|
||||
All pull requests must include a brief but descriptive title, and a detailed description of the changes that you've made. **Only include commits that are related to your feature, bug fix, or patch in your pull request!**
|
||||
|
||||
## Thank you
|
||||
|
||||
We appreciate **all** contributions no matter what size; your feedback and input directly shapes the future of Hestia Control Panel and we could not do it without your support.
|
||||
|
||||
Thank you for your time and we look forward to seeing your pull requests,<br>
|
||||
The Hestia Control Panel development team
|
@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
@ -0,0 +1,138 @@
|
||||
<h1 align="center"><a href="https://www.hestiacp.com/">Hestia Control Panel</a></h1>
|
||||
|
||||

|
||||
|
||||
<h2 align="center">Lightweight and powerful control panel for the modern web</h2>
|
||||
|
||||
<p align="center"><strong>Latest stable release:</strong> Version 1.8.2 | <a href="https://github.com/hestiacp/hestiacp/blob/release/CHANGELOG.md">View Changelog</a></p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.hestiacp.com/">HestiaCP.com</a> |
|
||||
<a href="https://docs.hestiacp.com/">Documentation</a> |
|
||||
<a href="https://forum.hestiacp.com/">Forum</a>
|
||||
<br/><br/>
|
||||
<a href="https://drone.hestiacp.com/hestiacp/hestiacp">
|
||||
<img src="https://drone.hestiacp.com/api/badges/hestiacp/hestiacp/status.svg?ref=refs/heads/main" alt="Drone Status"/>
|
||||
</a>
|
||||
<a href="https://github.com/hestiacp/hestiacp/actions/workflows/lint.yml">
|
||||
<img src="https://github.com/hestiacp/hestiacp/actions/workflows/lint.yml/badge.svg" alt="Lint Status"/>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## **Welcome!**
|
||||
|
||||
Hestia Control Panel is designed to provide administrators an easy to use web and command line interface, enabling them to quickly deploy and manage web domains, mail accounts, DNS zones, and databases from one central dashboard without the hassle of manually deploying and configuring individual components or services.
|
||||
|
||||
## Donate
|
||||
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ST87LQH2CHGLA)<br /><br />
|
||||
Bitcoin : bc1q48jt5wg5jaj8g9zy7c3j03cv57j2m2u5anlutu<br>
|
||||
Ethereum : 0xfF3Dd2c889bd0Ff73d8085B84A314FC7c88e5D51<br>
|
||||
Binance: bnb1l4ywvw5ejfmsgjdcx8jn5lxj7zsun8ktfu7rh8<br>
|
||||
Smart Chain: 0xfF3Dd2c889bd0Ff73d8085B84A314FC7c88e5D51<br>
|
||||
|
||||
## Features and Services
|
||||
|
||||
- Apache2 and NGINX with PHP-FPM
|
||||
- Multiple PHP versions (5.6 - 8.2, 8.0 as default)
|
||||
- DNS Server (Bind) with clustering capabilities
|
||||
- POP/IMAP/SMTP mail services with Anti-Virus, Anti-Spam, and Webmail (ClamAV, SpamAssassin, Sieve, Roundcube)
|
||||
- MariaDB/MySQL and/or PostgreSQL databases
|
||||
- Let's Encrypt SSL support with wildcard certificates
|
||||
- Firewall with brute-force attack detection and IP lists (iptables, fail2ban, and ipset).
|
||||
|
||||
## Supported platforms and operating systems
|
||||
|
||||
- **Debian:** 12, 11, or 10
|
||||
- **Ubuntu:** 22.04 LTS, 20.04 LTS
|
||||
|
||||
**NOTES:**
|
||||
|
||||
- Hestia Control Panel does not support 32 bit operating systems!
|
||||
- Hestia Control Panel in combination with OpenVZ 7 or lower might have issues with DNS and/or firewall. If you use a Virtual Private Server we strongly advice you to use something based on KVM or LXC!
|
||||
|
||||
## Installing Hestia Control Panel
|
||||
|
||||
- **NOTE:** You must install Hestia Control Panel on top of a fresh operating system installation to ensure proper functionality.
|
||||
|
||||
While we have taken every effort to make the installation process and the control panel interface as friendly as possible (even for new users), it is assumed that you will have some prior knowledge and understanding in the basics how to set up a Linux server before continuing.
|
||||
|
||||
### Step 1: Log in
|
||||
|
||||
To start the installation, you will need to be logged in as **root** or a user with super-user privileges. You can perform the installation either directly from the command line console or remotely via SSH:
|
||||
|
||||
```bash
|
||||
ssh root@your.server
|
||||
```
|
||||
|
||||
### Step 2: Download
|
||||
|
||||
Download the installation script for the latest release:
|
||||
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/hestiacp/hestiacp/release/install/hst-install.sh
|
||||
```
|
||||
|
||||
If the download fails due to an SSL validation error, please be sure you've installed the ca-certificate package on your system - you can do this with the following command:
|
||||
|
||||
```bash
|
||||
apt-get update && apt-get install ca-certificates
|
||||
```
|
||||
|
||||
### Step 3: Run
|
||||
|
||||
To begin the installation process, simply run the script and follow the on-screen prompts:
|
||||
|
||||
```bash
|
||||
bash hst-install.sh
|
||||
```
|
||||
|
||||
You will receive a welcome email at the address specified during installation (if applicable) and on-screen instructions after the installation is completed to log in and access your server.
|
||||
|
||||
### Custom installation
|
||||
|
||||
You may specify a number of various flags during installation to only install the features in which you need. To view a list of available options, run:
|
||||
|
||||
```bash
|
||||
bash hst-install.sh -h
|
||||
```
|
||||
|
||||
Alternatively, You can use <https://hestiacp.com/install.html> which allows you to easily generate the installation command via GUI.
|
||||
|
||||
## How to upgrade an existing installation
|
||||
|
||||
Automatic Updates are enabled by default on new installations of Hestia Control Panel and can be managed from **Server Settings > Updates**. To manually check for and install available updates, use the apt package manager:
|
||||
|
||||
```bash
|
||||
apt-get update
|
||||
apt-get upgrade
|
||||
```
|
||||
|
||||
## Issues & Support Requests
|
||||
|
||||
- If you encounter a general problem while using Hestia Control Panel and need help, please [visit our forum](https://forum.hestiacp.com/) to search for potential solutions or post a new thread where community members can assist.
|
||||
- Bugs and other reproducible issues should be filed via GitHub by [creating a new issue report](https://github.com/hestiacp/hestiacp/issues) so that our developers can investigate further. Please note that requests for support will be redirected to our forum.
|
||||
|
||||
**IMPORTANT: We _cannot_ provide support for requests that do not describe the troubleshooting steps that have already been performed, or for third-party applications not related to Hestia Control Panel (such as WordPress). Please make sure that you include as much information as possible in your forum posts or issue reports!**
|
||||
|
||||
## Contributions
|
||||
|
||||
If you would like to contribute to the project, please [read our Contribution Guidelines](https://github.com/hestiacp/hestiacp/blob/release/CONTRIBUTING.md) for a brief overview of our development process and standards.
|
||||
|
||||
## Copyright
|
||||
|
||||
"Hestia Control Panel", "HestiaCP", and the Hestia logo are original copyright of hestiacp.com and the following restrictions apply:
|
||||
|
||||
**You are allowed to:**
|
||||
|
||||
- use the names "Hestia Control Panel", "HestiaCP", or the Hestia logo in any context directly related to the application or the project. This includes the application itself, local communities and news or blog posts.
|
||||
|
||||
**You are not allowed to:**
|
||||
|
||||
- sell or redistribute the application under the name "Hestia Control Panel", "HestiaCP", or similar derivatives, including the use of the Hestia logo in any brand or marketing materials related to revenue generating activities,
|
||||
- use the names "Hestia Control Panel", "HestiaCP", or the Hestia logo in any context that is not related to the project,
|
||||
- alter the name "Hestia Control Panel", "HestiaCP", or the Hestia logo in any way.
|
||||
|
||||
## License
|
||||
|
||||
Hestia Control Panel is licensed under [GPL v3](https://github.com/hestiacp/hestiacp/blob/release/LICENSE) license, and is based on the [VestaCP](https://vestacp.com/) project.<br>
|
@ -0,0 +1,81 @@
|
||||
#!/bin/bash
|
||||
# info: update user notification
|
||||
# options: USER NOTIFICATION
|
||||
#
|
||||
# example: v-acknowledge-user-notification
|
||||
#
|
||||
# This function updates user notification.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
id=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER NOTIFICATION'
|
||||
if [ "$id" = "all" ]; then
|
||||
is_format_valid 'user'
|
||||
else
|
||||
is_format_valid 'user' 'id'
|
||||
fi
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Updating notification
|
||||
if [ "$id" = 'all' ]; then
|
||||
for id in $(v-list-user-notifications admin plain | cut -f1); do
|
||||
update_object_value 'notifications' 'NID' "$id" '$ACK' 'yes' 2> /dev/null
|
||||
done
|
||||
else
|
||||
update_object_value 'notifications' 'NID' "$id" '$ACK' 'yes' 2> /dev/null
|
||||
|
||||
# Checking last notification
|
||||
if [ -e "$USER_DATA/notifications.conf" ]; then
|
||||
if [ -z "$(grep NID= $USER_DATA/notifications.conf)" ]; then
|
||||
notice='no'
|
||||
fi
|
||||
if [ -z "$(grep "ACK='no'" $USER_DATA/notifications.conf)" ]; then
|
||||
notice='no'
|
||||
fi
|
||||
else
|
||||
notice='no'
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Updating notification counter
|
||||
if [ "$notice" = 'no' ]; then
|
||||
if [ -z "$(grep NOTIFICATIONS $USER_DATA/user.conf)" ]; then
|
||||
sed -i "s/^TIME/NOTIFICATIONS='no'\nTIME/g" $USER_DATA/user.conf
|
||||
else
|
||||
update_user_value "$user" '$NOTIFICATIONS' "no"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,106 @@
|
||||
#!/bin/bash
|
||||
# info: generate access key
|
||||
# options: USER [PERMISSIONS] [COMMENT] [FORMAT]
|
||||
#
|
||||
# example: v-add-access-key admin v-purge-nginx-cache,v-list-mail-accounts comment json
|
||||
#
|
||||
# The "PERMISSIONS" argument is optional for the admin user only.
|
||||
# This function creates a key file in $HESTIA/data/access-keys/
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
permissions=$2
|
||||
comment=$3
|
||||
format=${4-shell}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
keygen() {
|
||||
local LENGTH=${1:-20}
|
||||
local USE_SPECIAL_CHARACTERS="${2:-no}"
|
||||
|
||||
local MATRIX='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
|
||||
if [[ "$USE_SPECIAL_CHARACTERS" == "yes" ]]; then
|
||||
MATRIX+='_-='
|
||||
fi
|
||||
|
||||
local PASS N
|
||||
while [ ${N:=1} -le $LENGTH ]; do
|
||||
PASS="$PASS${MATRIX:$(($RANDOM % ${#MATRIX})):1}"
|
||||
let N+=1
|
||||
done
|
||||
|
||||
echo "$PASS"
|
||||
}
|
||||
|
||||
access_key_id="$(keygen)"
|
||||
secret_access_key="$(keygen 40 yes)"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
# Remove whitespace and bin path from permissions
|
||||
permissions="$(cleanup_key_permissions "$permissions")"
|
||||
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'USER [PERMISSIONS] [COMMENT] [FORMAT]'
|
||||
is_format_valid 'user' 'comment' 'format'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_key_permissions_format_valid "$permissions" "$user"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ ! -d "$HESTIA/data/access-keys/" ]; then
|
||||
mkdir -p $HESTIA/data/access-keys/
|
||||
chown root:root $HESTIA/data/access-keys/
|
||||
chmod 750 $HESTIA/data/access-keys/
|
||||
fi
|
||||
|
||||
if [[ -e "$HESTIA/data/access-keys/${access_key_id}" ]]; then
|
||||
while [[ -e "$HESTIA/data/access-keys/${access_key_id}" ]]; do
|
||||
access_key_id=$(keygen)
|
||||
done
|
||||
fi
|
||||
|
||||
echo "SECRET_ACCESS_KEY='$secret_access_key'" > "$HESTIA/data/access-keys/${access_key_id}"
|
||||
echo "USER='$user'" >> "$HESTIA/data/access-keys/${access_key_id}"
|
||||
echo "PERMISSIONS='$permissions'" >> "$HESTIA/data/access-keys/${access_key_id}"
|
||||
echo "COMMENT='$comment'" >> "$HESTIA/data/access-keys/${access_key_id}"
|
||||
echo "TIME='$time'" >> "$HESTIA/data/access-keys/${access_key_id}"
|
||||
echo "DATE='$date'" >> "$HESTIA/data/access-keys/${access_key_id}"
|
||||
# TODO Index reserved for future implementation
|
||||
echo "EXPIRES_IN=''" >> "$HESTIA/data/access-keys/${access_key_id}"
|
||||
echo "IP=''" >> "$HESTIA/data/access-keys/${access_key_id}"
|
||||
|
||||
chmod 640 "$HESTIA/data/access-keys/${access_key_id}"
|
||||
|
||||
$BIN/v-list-access-key "$access_key_id" "$format"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
log_history "Access key $access_key_id generated" "Warning" "$user" "API"
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,344 @@
|
||||
#!/bin/bash
|
||||
# info: add backup host
|
||||
# options: TYPE HOST USERNAME PASSWORD [PATH] [PORT]
|
||||
#
|
||||
# example: v-add-backup-host sftp backup.acme.com admin p4$$w@Rd
|
||||
# v-add-backup-host b2 bucketName keyID applicationKey
|
||||
#
|
||||
# Add a new remote backup location. Currently SFTP, FTP and Backblaze are supported
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
type=$1
|
||||
host=$2
|
||||
user=$3
|
||||
raw_password=$4
|
||||
HIDE=4
|
||||
password=$(perl -e 'print quotemeta shift(@ARGV)' "${raw_password}")
|
||||
path=${5-/backup}
|
||||
port=$6
|
||||
|
||||
# CPU Architecture
|
||||
arch=$(arch)
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
# Fetch current verison B2 CLI tool
|
||||
source_conf "$HESTIA/install/upgrade/upgrade.conf"
|
||||
|
||||
# Paths
|
||||
b2cli="/usr/local/bin/b2"
|
||||
b2lnk="https://github.com/Backblaze/B2_Command_Line_Tool/releases/download/v$b2_v/b2-linux"
|
||||
|
||||
# Defining ftp command function
|
||||
ftpc() {
|
||||
ftp -p -n $host $port << EOF
|
||||
quote USER $user
|
||||
quote PASS $password
|
||||
binary
|
||||
$1
|
||||
$2
|
||||
$3
|
||||
quit
|
||||
EOF
|
||||
}
|
||||
|
||||
# Defining sftp command function
|
||||
sftpc() {
|
||||
if [ "$privatekey" != "yes" ]; then
|
||||
expect -f "-" "$@" << EOF
|
||||
set count 0
|
||||
spawn /usr/bin/sftp -o StrictHostKeyChecking=no -o Port=$port $user@$host
|
||||
expect {
|
||||
-nocase "password:" {
|
||||
send "$password\r"
|
||||
exp_continue
|
||||
}
|
||||
|
||||
-re "Password for (.*)@(.*)" {
|
||||
send "$password\r"
|
||||
exp_continue
|
||||
}
|
||||
|
||||
-re "Couldn't|(.*)disconnect|(.*)stalled|(.*)not found" {
|
||||
set count \$argc
|
||||
set output "Disconnected."
|
||||
set rc $E_FTP
|
||||
exp_continue
|
||||
}
|
||||
|
||||
-re ".*denied.*(publickey|password)." {
|
||||
set output "Permission denied, wrong publickey or password."
|
||||
set rc $E_CONNECT
|
||||
}
|
||||
|
||||
"sftp>" {
|
||||
if {\$count < \$argc} {
|
||||
set arg [lindex \$argv \$count]
|
||||
send "\$arg\r"
|
||||
incr count
|
||||
} else {
|
||||
send "exit\r"
|
||||
set output "Disconnected."
|
||||
if {[info exists rc] != 1} {
|
||||
set rc $OK
|
||||
}
|
||||
}
|
||||
exp_continue
|
||||
}
|
||||
|
||||
timeout {
|
||||
set output "Connection timeout."
|
||||
set rc $E_CONNECT
|
||||
}
|
||||
}
|
||||
|
||||
if {[info exists output] == 1} {
|
||||
puts "\$output"
|
||||
}
|
||||
|
||||
exit \$rc
|
||||
EOF
|
||||
else
|
||||
expect -f "-" "$@" << EOF
|
||||
set count 0
|
||||
spawn /usr/bin/sftp -o StrictHostKeyChecking=no -o Port=$port -i $raw_password $user@$host
|
||||
expect {
|
||||
|
||||
-re "Couldn't|(.*)disconnect|(.*)stalled|(.*)not found" {
|
||||
set count \$argc
|
||||
set output "Disconnected."
|
||||
set rc $E_FTP
|
||||
exp_continue
|
||||
}
|
||||
|
||||
-re ".*denied.*(publickey|password)." {
|
||||
set output "Permission denied, wrong publickey or password."
|
||||
set rc $E_CONNECT
|
||||
}
|
||||
|
||||
"sftp>" {
|
||||
if {\$count < \$argc} {
|
||||
set arg [lindex \$argv \$count]
|
||||
send "\$arg\r"
|
||||
incr count
|
||||
} else {
|
||||
send "exit\r"
|
||||
set output "Disconnected."
|
||||
if {[info exists rc] != 1} {
|
||||
set rc $OK
|
||||
}
|
||||
}
|
||||
exp_continue
|
||||
}
|
||||
|
||||
timeout {
|
||||
set output "Connection timeout."
|
||||
set rc $E_CONNECT
|
||||
}
|
||||
}
|
||||
|
||||
if {[info exists output] == 1} {
|
||||
puts "\$output"
|
||||
}
|
||||
|
||||
exit \$rc
|
||||
EOF
|
||||
fi
|
||||
}
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ "$type" != 'local' ]; then
|
||||
check_args '2' "$#" "TYPE HOST USERNAME PASSWORD [PATH] [PORT]"
|
||||
is_format_valid 'host' 'path' 'port'
|
||||
is_type_valid 'sftp,ftp,b2,rclone' "$type"
|
||||
is_username_format_valid "$user" "username"
|
||||
privatekey="no"
|
||||
if [ -f "$raw_password" ]; then
|
||||
if [[ $(cat "$raw_password" | grep "OPENSSH PRIVATE") ]]; then
|
||||
privatekey="yes"
|
||||
password="$raw_password"
|
||||
else
|
||||
is_password_valid
|
||||
fi
|
||||
else
|
||||
is_password_valid
|
||||
fi
|
||||
format_no_quotes "$password" "password"
|
||||
|
||||
if [ "$type" = 'sftp' ]; then
|
||||
which expect > /dev/null 2>&1
|
||||
check_result $? "expect command not found" "$E_NOTEXIST"
|
||||
fi
|
||||
if [ "$type" != 'b2' ] && [ "$type" != 'rclone' ]; then
|
||||
if ! (is_ip_format_valid "$host" > /dev/null); then
|
||||
host "$host" > /dev/null 2>&1
|
||||
check_result $? "host connection failed" "$E_CONNECT"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Checking network connection
|
||||
if [ "$type" = 'ftp' ]; then
|
||||
if [ -z $port ]; then
|
||||
port=21
|
||||
fi
|
||||
fconn=$(ftpc 2>&1)
|
||||
ferror=$(echo $fconn \
|
||||
| grep -i -e failed -e error -e "can't" -e "not conn" -e "incorrect")
|
||||
if [ -n "$ferror" ]; then
|
||||
echo "Error: can't login to ftp $user@$host"
|
||||
log_event "$E_CONNECT" "$ARGUMENTS"
|
||||
exit "$E_CONNECT"
|
||||
fi
|
||||
|
||||
# Checking write permissions
|
||||
if [ -z $path ]; then
|
||||
ftmpdir="vst.bK76A9SUkt"
|
||||
else
|
||||
ftpc "mkdir $path" > /dev/null 2>&1
|
||||
ftmpdir="$path/vst.bK76A9SUkt"
|
||||
fi
|
||||
ftp_result=$(ftpc "mkdir $ftmpdir" "rm $ftmpdir" | grep -v Trying)
|
||||
if [ -n "$ftp_result" ]; then
|
||||
echo "$ftp_result"
|
||||
rm -rf $tmpdir
|
||||
echo "Error: can't create $ftmpdir folder on the ftp"
|
||||
log_event "$E_FTP" "$ARGUMENTS"
|
||||
exit "$E_FTP"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$type" = 'sftp' ]; then
|
||||
if [ -z $port ]; then
|
||||
port=22
|
||||
fi
|
||||
if [ -z $path ]; then
|
||||
sftmpdir="vst.bK76A9SUkt"
|
||||
sftpc "mkdir $sftmpdir" "rmdir $sftmpdir" > /dev/null 2>&1
|
||||
else
|
||||
if sftpc "mkdir $path" > /dev/null 2>&1; then
|
||||
sftmpdir="$path/vst.bK76A9SUkt"
|
||||
sftpc "mkdir $sftmpdir" "rmdir $sftmpdir" > /dev/null 2>&1
|
||||
else
|
||||
sftmpdir="$path/vst.bK76A9SUkt"
|
||||
sftpc "mkdir $sftmpdir" "rmdir $sftmpdir" > /dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
rc=$?
|
||||
if [[ "$rc" != 0 ]]; then
|
||||
case $rc in
|
||||
$E_CONNECT) echo "Error: can't login to sftp $user@$host" ;;
|
||||
$E_FTP) echo "Error: can't create temp folder on the sftp host" ;;
|
||||
esac
|
||||
log_event "$rc" "$ARGUMENTS"
|
||||
exit "$rc"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$type" = 'b2' ]; then
|
||||
# Download b2 binary
|
||||
if [ ! -f "$b2cli" ]; then
|
||||
if [ "$arch" = 'aarch64' ] || [ "$arch" = 'arm64' ]; then
|
||||
echo "Error: B2 binary for arm64 must be downloaded manually."
|
||||
exit 3
|
||||
else
|
||||
wget -O $b2cli $b2lnk > /dev/null 2>&1
|
||||
chmod +x $b2cli > /dev/null 2>&1
|
||||
fi
|
||||
if [ ! -f "$b2cli" ]; then
|
||||
echo "Error: Binary download failed, b2 doesn't work as expected."
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
|
||||
# Validate b2 binary
|
||||
b2version="$(b2 version)"
|
||||
if [[ ! "$b2version" =~ "b2 command line tool" ]]; then
|
||||
echo "Error: Binary download failed, b2 doesn't work as expected."
|
||||
exit 3
|
||||
fi
|
||||
|
||||
b2 clear-account > /dev/null 2>&1
|
||||
b2 authorize-account "$user" "$raw_password" > /dev/null 2>&1
|
||||
b2 ls --long "$host" "$user" > /dev/null 2>&1
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
check_result "$E_CONNECT" "b2 failed to verify connection"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$type" = 'rclone' ]; then
|
||||
curl -s https://rclone.org/install.sh | bash /dev/null > /dev/null 2>&1
|
||||
# Verify account exists
|
||||
if [ ! -z "$(cat /root/.config/rclone/rclone.conf | grep "\[$host\]")" ]; then
|
||||
echo "test" > /tmp/hestia-backup.txt
|
||||
# Try to upload a single file
|
||||
if [ -z "$path" ]; then
|
||||
rclone copy /tmp/hestia-backup.txt $host:/hestia-backup.txt
|
||||
rclone delete $host:/hestia-backup.txt
|
||||
else
|
||||
rclone copy /tmp/hestia-backup.txt $host:$path/hestia-backup.txt
|
||||
rclone delete $host:$path/hestia-backup.txt
|
||||
fi
|
||||
else
|
||||
check_result "$E_CONNECT" "Rclone config does not exist"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Adding backup host
|
||||
if [ $type == 'ftp' ] || [ $type = 'sftp' ]; then
|
||||
new_timestamp
|
||||
str="HOST='$host'\nUSERNAME='$user'\nPASSWORD='$password'\nPRIVATEKEY='$privatekey'"
|
||||
str="$str\nBPATH='$path'\nPORT='$port'\nTIME='$time'\nDATE='$date'"
|
||||
echo -e "$str" > $HESTIA/conf/$type.backup.conf
|
||||
chmod 660 $HESTIA/conf/$type.backup.conf
|
||||
elif [ $type == 'b2' ]; then
|
||||
new_timestamp
|
||||
str="BUCKET='$host'\nB2_KEYID='$user'\nB2_KEY='$raw_password'"
|
||||
str="$str\nTIME='$time'\nDATE='$date'"
|
||||
echo -e "$str" > $HESTIA/conf/$type.backup.conf
|
||||
chmod 660 $HESTIA/conf/$type.backup.conf
|
||||
elif [ $type == "rclone" ]; then
|
||||
new_timestamp
|
||||
str="HOST='$host'\nBPATH='$path'"
|
||||
str="$str\nTIME='$time'\nDATE='$date'"
|
||||
echo -e "$str" > $HESTIA/conf/$type.backup.conf
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Update hestia.conf
|
||||
if [ -z "$(grep BACKUP_SYSTEM $HESTIA/conf/hestia.conf)" ]; then
|
||||
echo "BACKUP_SYSTEM='$type'" >> $HESTIA/conf/hestia.conf
|
||||
else
|
||||
bckp=$(echo "$BACKUP_SYSTEM,$type" \
|
||||
| sed "s/,/\n/g" \
|
||||
| sort -r -u \
|
||||
| sed "/^$/d" \
|
||||
| sed ':a;N;$!ba;s/\n/,/g')
|
||||
sed -i "s/BACKUP_SYSTEM=.*/BACKUP_SYSTEM='$bckp'/g" $HESTIA/conf/hestia.conf
|
||||
fi
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,99 @@
|
||||
#!/bin/bash
|
||||
# info: add cron job for hestia automatic updates
|
||||
# options: MODE
|
||||
#
|
||||
# This function adds a cronjob for hestia automatic updates
|
||||
# that can be downloaded from apt or git.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=admin
|
||||
mode=$1
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
is_system_enabled "$CRON_SYSTEM" 'CRON_SYSTEM'
|
||||
is_package_full 'CRON_JOBS'
|
||||
get_next_cronjob
|
||||
check_cron_apt=$(grep 'v-update-sys-hestia-all' $USER_DATA/cron.conf)
|
||||
check_cron_git=$(grep 'v-update-sys-hestia-git' $USER_DATA/cron.conf)
|
||||
if [ -n "$check_cron_apt" ] || [ -n "$check_cron_git" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Define time somewhere at night
|
||||
if [ -z "$mode" ] || [ "$mode" = "apt" ]; then
|
||||
min=$(generate_password '012345' '2')
|
||||
hour=$(generate_password '1234567' '1')
|
||||
day='*'
|
||||
month='*'
|
||||
wday='*'
|
||||
command="sudo $BIN/v-update-sys-hestia-all"
|
||||
fi
|
||||
|
||||
if [ "$mode" = "git" ]; then
|
||||
min='0'
|
||||
hour='0'
|
||||
day='*'
|
||||
month='*'
|
||||
wday='*'
|
||||
command="sudo $BIN/v-update-sys-hestia-git"
|
||||
fi
|
||||
|
||||
# Concatenating cron string
|
||||
str="JOB='$job' MIN='$min' HOUR='$hour' DAY='$day' MONTH='$month' WDAY='$wday'"
|
||||
str="$str CMD='$command' SUSPENDED='no' TIME='$time' DATE='$date'"
|
||||
|
||||
# Adding to crontab
|
||||
echo "$str" >> $HESTIA/data/users/$user/cron.conf
|
||||
|
||||
# Changing permissions
|
||||
chmod 660 $HESTIA/data/users/$user/cron.conf
|
||||
|
||||
# Sort jobs by id number
|
||||
sort_cron_jobs
|
||||
|
||||
# Sync cronjobs with system cron
|
||||
sync_cron_jobs
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Increasing cron value
|
||||
increase_user_value "$user" '$U_CRON_JOBS'
|
||||
|
||||
# Restarting cron
|
||||
$BIN/v-restart-cron
|
||||
check_result $? "Cron restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "Updates" "Automatic updates enabled."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,93 @@
|
||||
#!/bin/bash
|
||||
# info: add cron job
|
||||
# options: USER MIN HOUR DAY MONTH WDAY COMMAND [JOB] [RESTART]
|
||||
#
|
||||
# example: v-add-cron-job admin * * * * * sudo /usr/local/hestia/bin/v-backup-users
|
||||
#
|
||||
# This function adds a job to cron daemon. When executing commands, any output
|
||||
# is mailed to user's email if parameter REPORTS is set to 'yes'.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
min=$2
|
||||
hour=$3
|
||||
day=$4
|
||||
month=$5
|
||||
wday=$6
|
||||
command=$(echo $7 | sed "s/'/%quote%/g")
|
||||
job=$8
|
||||
restart=$9
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
HIDE=7
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '7' "$#" 'USER MIN HOUR DAY MONTH WDAY COMMAND [JOB] [RESTART]'
|
||||
is_format_valid 'user' 'min' 'hour' 'day' 'month' 'wday' 'command'
|
||||
is_system_enabled "$CRON_SYSTEM" 'CRON_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_package_full 'CRON_JOBS'
|
||||
get_next_cronjob
|
||||
is_format_valid 'job'
|
||||
is_format_valid 'restart'
|
||||
is_object_new 'cron' 'JOB' "$job"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Concatenating cron string
|
||||
str="JOB='$job' MIN='$min' HOUR='$hour' DAY='$day' MONTH='$month' WDAY='$wday'"
|
||||
str="$str CMD='$command' SUSPENDED='no' TIME='$time' DATE='$date'"
|
||||
|
||||
# Adding to crontab
|
||||
echo "$str" >> $HESTIA/data/users/$user/cron.conf
|
||||
|
||||
# Changing permissions
|
||||
chmod 660 $HESTIA/data/users/$user/cron.conf
|
||||
|
||||
# Sort jobs by id number
|
||||
sort_cron_jobs
|
||||
|
||||
# Sync cronjobs with system crond
|
||||
sync_cron_jobs
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Increasing cron value
|
||||
increase_user_value $user '$U_CRON_JOBS'
|
||||
|
||||
# Restarting cron
|
||||
$BIN/v-restart-cron "$restart"
|
||||
check_result $? "Cron restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Cron Jobs" "Cron job added (ID: $job, Command: $command)"
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
# info: add cron job for Let's Encrypt certificates
|
||||
# options: NONE
|
||||
#
|
||||
# This function adds a new cron job for Let's Encrypt.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
is_system_enabled "$CRON_SYSTEM" 'CRON_SYSTEM'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Add cron job
|
||||
cmd="sudo $BIN/v-update-sys-queue letsencrypt"
|
||||
check_cron=$(grep "$cmd" $HESTIA/data/users/admin/cron.conf 2> /dev/null)
|
||||
if [ -z "$check_cron" ] && [ -n "$CRON_SYSTEM" ]; then
|
||||
$BIN/v-add-cron-job admin '*/5' '*' '*' '*' '*' "$cmd"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,60 @@
|
||||
#!/bin/bash
|
||||
# info: add cron reports
|
||||
# options: USER
|
||||
#
|
||||
# example: v-add-cron-reports admin
|
||||
#
|
||||
# This function for enabling reports on cron tasks and administrative
|
||||
# notifications.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'USER'
|
||||
is_format_valid 'user'
|
||||
is_system_enabled "$CRON_SYSTEM" 'CRON_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Changing user report value
|
||||
update_user_value "$user" '$CRON_REPORTS' 'yes'
|
||||
|
||||
# Sync system cron with user
|
||||
sync_cron_jobs
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Restart cron
|
||||
$BIN/v-restart-cron
|
||||
check_result $? "Cron restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Cron Jobs" "Cron job notifications and reporting enabled."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
# info: add cron reports
|
||||
# options: NONE
|
||||
#
|
||||
# This function for enabling restart cron tasks
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
is_system_enabled "$CRON_SYSTEM" 'CRON_SYSTEM'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Add cron job
|
||||
cmd="sudo $BIN/v-update-sys-queue restart"
|
||||
check_cron=$(grep "$cmd" $HESTIA/data/users/admin/cron.conf 2> /dev/null)
|
||||
if [ -z "$check_cron" ] && [ -n "$CRON_SYSTEM" ]; then
|
||||
$BIN/v-add-cron-job admin '*' '*' '*' '*' '*' "$cmd"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,113 @@
|
||||
#!/bin/bash
|
||||
# info: add database
|
||||
# options: USER DATABASE DBUSER DBPASS [TYPE] [HOST] [CHARSET]
|
||||
#
|
||||
# example: v-add-database admin wordpress_db matt qwerty123
|
||||
#
|
||||
# This function creates the database concatenating username and user_db.
|
||||
# Supported types of databases you can get using v-list-sys-config script.
|
||||
# If the host isn't stated and there are few hosts configured on the server,
|
||||
# then the host will be defined by one of three algorithms. "First" will choose
|
||||
# the first host in the list. "Random" will chose the host by a chance.
|
||||
# "Weight" will distribute new database through hosts evenly. Algorithm and
|
||||
# types of supported databases is designated in the main configuration file.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
database="$user"_"$2"
|
||||
dbuser="$user"_"$3"
|
||||
password=$4
|
||||
HIDE=4
|
||||
type=${5-mysql}
|
||||
host=$6
|
||||
charset=${7-UTF8MB4}
|
||||
charset=$(echo "$charset" | tr '[:lower:]' '[:upper:]')
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/db.sh
|
||||
source $HESTIA/func/db.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
if [ "$type" = "pgsql" ]; then
|
||||
database=$(echo "$user"_"$2" | tr '[:upper:]' '[:lower:]')
|
||||
dbuser=$(echo "$user"_"$3" | tr '[:upper:]' '[:lower:]')
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '4' "$#" 'USER DATABASE DBUSER DBPASS [TYPE] [HOST] [CHARSET]'
|
||||
is_format_valid 'user' 'database' 'dbuser' 'charset'
|
||||
is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM'
|
||||
is_type_valid "$DB_SYSTEM" "$type"
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_new 'db' 'DB' "$database"
|
||||
is_object_new 'db' 'DBUSER' "$dbuser"
|
||||
get_next_dbhost
|
||||
is_object_valid "../../../conf/$type" 'HOST' "$host"
|
||||
is_object_unsuspended "../../../conf/$type" 'DBHOST' "$host"
|
||||
#is_charset_valid
|
||||
is_package_full 'DATABASES'
|
||||
is_password_valid
|
||||
|
||||
if [ "$type" = "pgsql" ]; then
|
||||
exclude="-"
|
||||
if [[ "$dbuser" =~ $exclude ]]; then
|
||||
check_result "$E_INVALID" "invalid database user format"
|
||||
fi
|
||||
if [[ "$database" =~ $exclude ]]; then
|
||||
check_result "$E_INVALID" "invalid database format"
|
||||
fi
|
||||
fi
|
||||
|
||||
dbpass="$password"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Switching on db type
|
||||
case $type in
|
||||
mysql) add_mysql_database ;;
|
||||
pgsql) add_pgsql_database ;;
|
||||
esac
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Adding db to db conf
|
||||
str="DB='$database' DBUSER='$dbuser' MD5='$md5' HOST='$host' TYPE='$type'"
|
||||
str="$str CHARSET='$charset' U_DISK='0' SUSPENDED='no' TIME='$time'"
|
||||
str="$str DATE='$date'"
|
||||
echo "$str" >> $USER_DATA/db.conf
|
||||
chmod 660 $USER_DATA/db.conf
|
||||
|
||||
# Increasing counters
|
||||
increase_dbhost_values
|
||||
increase_user_value "$user" '$U_DATABASES'
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Databases" "Added new database $database ($type)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,169 @@
|
||||
#!/bin/bash
|
||||
# info: add new database server
|
||||
# options: TYPE HOST DBUSER DBPASS [MAX_DB] [CHARSETS] [TEMPLATE] [PORT]
|
||||
#
|
||||
# example: v-add-database-host mysql localhost alice p@$$wOrd
|
||||
#
|
||||
# This function add new database server to the server pool. It supports local
|
||||
# and remote database servers, which is useful for clusters. By adding a host
|
||||
# you can set limit for number of databases on a host. Template parameter is
|
||||
# used only for PostgreSQL and has an default value "template1". You can read
|
||||
# more about templates in official PostgreSQL documentation.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
type=$1
|
||||
host=$2
|
||||
dbuser=$3
|
||||
password=$4
|
||||
HIDE=4
|
||||
max_db=${5-500}
|
||||
charsets=${6}
|
||||
template=${7}
|
||||
port=${8}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/db.sh
|
||||
source $HESTIA/func/db.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
is_mysql_host_alive() {
|
||||
mycnf=$(mktemp)
|
||||
echo "[client]" > $mycnf
|
||||
echo "host='$host'" >> $mycnf
|
||||
echo "user='$dbuser'" >> $mycnf
|
||||
echo "password='$password'" >> $mycnf
|
||||
echo "port='$port'" >> $mycnf
|
||||
|
||||
chmod 600 $mycnf
|
||||
mysql_out=$(mktemp)
|
||||
if [ -f '/usr/bin/mariadb' ]; then
|
||||
mariadb --defaults-file=$mycnf -e 'SELECT VERSION()' > $mysql_out 2>&1
|
||||
else
|
||||
mysql --defaults-file=$mycnf -e 'SELECT VERSION()' > $mysql_out 2>&1
|
||||
fi
|
||||
if [ "$?" -ne '0' ]; then
|
||||
echo "Error: MySQL connection to $host failed"
|
||||
rm $mycnf
|
||||
log_event "$E_CONNECT" "$ARGUMENTS"
|
||||
exit "$E_CONNECT"
|
||||
fi
|
||||
|
||||
if [ -f '/usr/bin/mariadb' ]; then
|
||||
grants=$(mariadb --defaults-file=$mycnf -e 'SHOW GRANTS FOR CURRENT_USER();')
|
||||
else
|
||||
grants=$(mysql --defaults-file=$mycnf -e 'SHOW GRANTS FOR CURRENT_USER();')
|
||||
fi
|
||||
|
||||
if [ "$?" -ne '0' ]; then
|
||||
echo "Error: MySQL connection to $host failed"
|
||||
rm $mycnf
|
||||
log_event "$E_CONNECT" "$ARGUMENTS"
|
||||
exit "$E_CONNECT"
|
||||
fi
|
||||
|
||||
# Check allow to grant user
|
||||
check_grants=$(echo $grants | grep "WITH GRANT OPTION")
|
||||
if [ -z "$check_grants" ]; then
|
||||
echo "Error: MySQL connection to $host failed. Unable to grant other users"
|
||||
rm $mycnf
|
||||
log_event "$E_CONNECT" "$ARGUMENTS"
|
||||
exit "$E_CONNECT"
|
||||
fi
|
||||
rm $mycnf
|
||||
}
|
||||
|
||||
is_pgsql_host_alive() {
|
||||
export PGPASSWORD="$dbpass"
|
||||
psql -h $host -U $dbuser -p $port -c "SELECT VERSION()" > /dev/null 2>&1
|
||||
if [ "$?" -ne '0' ]; then
|
||||
echo "Error: PostgreSQL connection to $host failed"
|
||||
log_event "$E_CONNECT" "$ARGUMENTS"
|
||||
exit "$E_CONNECT"
|
||||
fi
|
||||
}
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
args_usage='TYPE HOST DBUSER DBPASS [MAX_DB] [CHARSETS] [TPL] [PORT]'
|
||||
check_args '4' "$#" "$args_usage"
|
||||
|
||||
if [ -z $charsets ]; then charsets="UTF8,LATIN1,WIN1250,WIN1251,WIN1252,WIN1256,WIN1258,KOI8"; fi
|
||||
if [ -z $template ]; then template="template1"; fi
|
||||
|
||||
database_set_default_ports
|
||||
|
||||
is_format_valid 'host' 'dbuser' 'max_db' 'charsets' 'template' 'port'
|
||||
is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM'
|
||||
is_type_valid "$DB_SYSTEM" "$type"
|
||||
is_dbhost_new
|
||||
is_password_valid
|
||||
dbpass="$password"
|
||||
|
||||
case $type in
|
||||
mysql) is_mysql_host_alive ;;
|
||||
pgsql) is_pgsql_host_alive ;;
|
||||
esac
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Concatenating db host string
|
||||
case $type in
|
||||
mysql)
|
||||
str="HOST='$host' USER='$dbuser' PASSWORD='$dbpass'"
|
||||
str="$str CHARSETS='$charsets' MAX_DB='$max_db' U_SYS_USERS=''"
|
||||
str="$str U_DB_BASES='0' SUSPENDED='no' TIME='$time' DATE='$date' PORT='$port'"
|
||||
;;
|
||||
pgsql)
|
||||
str="HOST='$host' USER='$dbuser' PASSWORD='$dbpass'"
|
||||
str="$str CHARSETS='$charsets' TPL='$template' MAX_DB='$max_db'"
|
||||
str="$str U_SYS_USERS='' U_DB_BASES='0' SUSPENDED='no'"
|
||||
str="$str TIME='$time' DATE='$date' PORT='$port'"
|
||||
;;
|
||||
esac
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding host to conf
|
||||
echo "$str" >> $HESTIA/conf/$type.conf
|
||||
chmod 660 $HESTIA/conf/$type.conf
|
||||
|
||||
# Updating hestia.conf
|
||||
if [ -z "$(grep DB_SYSTEM $HESTIA/conf/hestia.conf)" ]; then
|
||||
echo "DB_SYSTEM='$type'" >> $HESTIA/conf/hestia.conf
|
||||
else
|
||||
db=$(echo "$DB_SYSTEM,$type" \
|
||||
| sed "s/,/\n/g" \
|
||||
| sort -r -u \
|
||||
| sed "/^$/d" \
|
||||
| sed ':a;N;$!ba;s/\n/,/g')
|
||||
sed -i "s/DB_SYSTEM=.*/DB_SYSTEM='$db'/g" $HESTIA/conf/hestia.conf
|
||||
fi
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "Database" "Added external $type database server ($host) to the system."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,87 @@
|
||||
#!/bin/bash
|
||||
# info: add temp database user
|
||||
# options: USER DATABASE [TYPE] [HOST] [TTL]
|
||||
#
|
||||
# example: v-add-database-temp-user wordress wordpress_db mysql
|
||||
#
|
||||
# This function creates an temporary database user mysql_sso_db_XXXXXXXX and a random password
|
||||
# The user has an limited validity and only granted access to the specific database
|
||||
# Returns json to be read SSO Script
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
database="$2"
|
||||
type=${3-mysql}
|
||||
host=$4
|
||||
ttl=$5
|
||||
|
||||
if [ "$ttl" == '' ]; then
|
||||
ttl=60
|
||||
fi
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/db.sh
|
||||
source $HESTIA/func/db.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DATABASE [TYPE] [HOST] [TTL]'
|
||||
is_format_valid 'user' 'database' 'ttl'
|
||||
is_type_valid "$DB_SYSTEM" "$type"
|
||||
is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'db' 'DB' "$database"
|
||||
is_object_unsuspended 'db' 'DB' "$database"
|
||||
get_next_dbhost
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Get database values
|
||||
get_database_values
|
||||
|
||||
#generate password and unique user
|
||||
dbpass=$(generate_password)
|
||||
dbuser="hestia_sso_$(generate_password)"
|
||||
|
||||
add_mysql_database_temp_user
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error: Unable to create temp user"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [[ "$ttl" -gt 0 ]]; then
|
||||
echo "$BIN/v-delete-database-temp-user $user $database $dbuser mysql $host" | at "now +${ttl} minute" > /dev/null 2>&1
|
||||
fi
|
||||
echo '{
|
||||
"login": {
|
||||
"user": "'$dbuser'",
|
||||
"password": "'$dbpass'"
|
||||
}
|
||||
}'
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Databases" "Granted user $dbuser access to database $database."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
exit
|
@ -0,0 +1,222 @@
|
||||
#!/bin/bash
|
||||
# info: add dns domain
|
||||
# options: USER DOMAIN IP [NS1] [NS2] [NS3] [NS4] [NS5] [NS6] [NS7] [NS8] [RESTART]
|
||||
#
|
||||
# example: v-add-dns-domain admin example.com ns1.example.com ns2.example.com '' '' '' '' '' '' yes
|
||||
#
|
||||
# This function adds DNS zone with records defined in the template. If the exp
|
||||
# argument isn't stated, the expiration date value will be set to next year.
|
||||
# The soa argument is responsible for the relevant record. By default the first
|
||||
# user's NS server is used. TTL is set as common for the zone and for all of
|
||||
# its records with a default value of 14400 seconds.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
ip=$3
|
||||
ns1=$4
|
||||
ns2=$5
|
||||
ns3=$6
|
||||
ns4=$7
|
||||
ns5=$8
|
||||
ns6=$9
|
||||
ns7=${10}
|
||||
ns8=${11}
|
||||
restart=${12}
|
||||
dnssec=${13}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/rebuild.sh
|
||||
source $HESTIA/func/rebuild.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
domain_utf=$(idn2 --quiet -d "$domain_idn")
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN IP [NS1] [NS2] [NS3] [..] [NS8] [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'ip'
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
|
||||
if [ "$($BIN/v-list-dns-domain $user $domain_utf plain | cut -f 1) " != "$domain" ]; then
|
||||
is_domain_new 'dns' "$domain_utf"
|
||||
fi
|
||||
if [ "$($BIN/v-list-dns-domain $user $domain_idn plain | cut -f 1) " != "$domain" ]; then
|
||||
is_domain_new 'dns' "$domain_idn"
|
||||
else
|
||||
is_domain_new 'dns' "$domain"
|
||||
fi
|
||||
if [ -z "$(is_ip_format_valid $domain)" ]; then
|
||||
echo "Error: Invalid domain format. IP address detected as input."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -n "$restart" ]; then
|
||||
is_format_valid 'restart'
|
||||
fi
|
||||
|
||||
if [ -n "$dnssec" ]; then
|
||||
is_boolean_format_valid "$dnssec" 'dnssec'
|
||||
fi
|
||||
|
||||
is_package_full 'DNS_DOMAINS'
|
||||
template=$(get_user_value '$DNS_TEMPLATE')
|
||||
is_dns_template_valid "$template"
|
||||
|
||||
is_base_domain_owner "$domain"
|
||||
|
||||
if [ -n "$ns1" ]; then
|
||||
ns1=$(echo $4 | sed -e 's/\.*$//g' -e 's/^\.*//g')
|
||||
is_format_valid 'ns1'
|
||||
fi
|
||||
if [ -n "$ns2" ]; then
|
||||
ns2=$(echo $5 | sed -e 's/\.*$//g' -e 's/^\.*//g')
|
||||
is_format_valid 'ns2'
|
||||
fi
|
||||
if [ -n "$ns3" ]; then
|
||||
ns3=$(echo $6 | sed -e 's/\.*$//g' -e 's/^\.*//g')
|
||||
is_format_valid 'ns3'
|
||||
fi
|
||||
if [ -n "$ns4" ]; then
|
||||
ns4=$(echo $7 | sed -e 's/\.*$//g' -e 's/^\.*//g')
|
||||
is_format_valid 'ns4'
|
||||
fi
|
||||
if [ -n "$ns5" ]; then
|
||||
ns5=$(echo $8 | sed -e 's/\.*$//g' -e 's/^\.*//g')
|
||||
is_format_valid 'ns5'
|
||||
fi
|
||||
if [ -n "$ns6" ]; then
|
||||
ns6=$(echo $9 | sed -e 's/\.*$//g' -e 's/^\.*//g')
|
||||
is_format_valid 'ns6'
|
||||
fi
|
||||
if [ -n "$ns7" ]; then
|
||||
ns7=$(echo ${10} | sed -e 's/\.*$//g' -e 's/^\.*//g')
|
||||
is_format_valid 'ns7'
|
||||
fi
|
||||
if [ -n "$ns8" ]; then
|
||||
ns8=$(echo ${11} | sed -e 's/\.*$//g' -e 's/^\.*//g')
|
||||
is_format_valid 'ns8'
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Defining NS variables
|
||||
if [ -z $ns2 ]; then
|
||||
i=1
|
||||
ns=$(get_user_value '$NS')
|
||||
for nameserver in ${ns//,/ }; do
|
||||
eval ns$i=$nameserver
|
||||
((++i))
|
||||
done
|
||||
fi
|
||||
soa="$ns1"
|
||||
exp=$(date +%F -d "+ 1 year")
|
||||
serial=$(date +'%Y%m%d01')
|
||||
ttl=14400
|
||||
|
||||
# Reading template
|
||||
template_data=$(cat "$DNSTPL/$template.tpl")
|
||||
|
||||
# Deleting unused nameservers
|
||||
if [ -z "$ns3" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns3%)
|
||||
fi
|
||||
if [ -z "$ns4" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns4%)
|
||||
fi
|
||||
if [ -z "$ns5" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns5%)
|
||||
fi
|
||||
if [ -z "$ns6" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns6%)
|
||||
fi
|
||||
if [ -z "$ns7" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns7%)
|
||||
fi
|
||||
if [ -z "$ns8" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns8%)
|
||||
fi
|
||||
if [ -z "$dnssec" ]; then
|
||||
dnssec="no"
|
||||
fi
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Adding dns zone to the user config
|
||||
echo "$template_data" \
|
||||
| sed -e "s/%ip%/$ip/g" \
|
||||
-e "s/%domain_idn%/$domain_idn/g" \
|
||||
-e "s/%domain%/$domain/g" \
|
||||
-e "s/%ns1%/$ns1/g" \
|
||||
-e "s/%ns2%/$ns2/g" \
|
||||
-e "s/%ns3%/$ns3/g" \
|
||||
-e "s/%ns4%/$ns4/g" \
|
||||
-e "s/%ns5%/$ns5/g" \
|
||||
-e "s/%ns6%/$ns6/g" \
|
||||
-e "s/%ns7%/$ns7/g" \
|
||||
-e "s/%ns8%/$ns8/g" \
|
||||
-e "s/%time%/$time/g" \
|
||||
-e "s/%date%/$date/g" > $USER_DATA/dns/$domain.conf
|
||||
|
||||
chmod 660 $USER_DATA/dns/$domain.conf
|
||||
records="$(wc -l $USER_DATA/dns/$domain.conf | cut -f 1 -d ' ')"
|
||||
|
||||
# Adding dns.conf record
|
||||
dns_rec="DOMAIN='$domain' IP='$ip' TPL='$template' TTL='$ttl' EXP='$exp'"
|
||||
dns_rec="$dns_rec SOA='$soa' SERIAL='$serial' SRC='' RECORDS='$records'"
|
||||
dns_rec="$dns_rec DNSSEC='$dnssec' KEY='' SLAVE='no' MASTER='' SUSPENDED='no' TIME='$time' DATE='$date'"
|
||||
|
||||
echo "$dns_rec" >> $USER_DATA/dns.conf
|
||||
chmod 660 $USER_DATA/dns.conf
|
||||
|
||||
rebuild_dns_domain_conf
|
||||
|
||||
# Updating dns-cluster queue
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
cmd="$BIN/v-add-remote-dns-domain $user $domain yes"
|
||||
echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Increasing domain value
|
||||
increase_user_value "$user" '$U_DNS_DOMAINS'
|
||||
increase_user_value "$user" '$U_DNS_RECORDS' "$records"
|
||||
|
||||
# Restart named
|
||||
$BIN/v-restart-dns $restart
|
||||
check_result $? "DNS restart failed"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "DNS" "Added new DNS domain (Name: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,91 @@
|
||||
#!/bin/bash
|
||||
# info: add dns domain or dns record after web domain alias
|
||||
# options: USER ALIAS IP [RESTART]
|
||||
#
|
||||
# example: v-add-dns-on-web-alias admin www.example.com 8.8.8.8
|
||||
#
|
||||
# This function adds dns domain or dns record based on web domain alias.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
alias=$2
|
||||
ip=$3
|
||||
restart=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER ALIAS IP [RESTART]'
|
||||
is_format_valid 'user' 'alias' 'ip' 'restart'
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
if [ -e "$USER_DATA/dns/$alias.conf" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
# Define additional vars
|
||||
sub_domain=$(echo "$alias" | awk -F '.' '{print $1}')
|
||||
top_domain=$(echo "$alias" | sed -e "s/^$sub_domain.//")
|
||||
domain_lvl=$(echo "$alias" | grep -o "\." | wc -l)
|
||||
|
||||
# Adding second level domain
|
||||
if [ "$domain_lvl" -eq 1 ] || [ "${#top_domain}" -le '6' ]; then
|
||||
$BIN/v-add-dns-domain \
|
||||
"$user" "$alias" "$ip" '' '' '' '' '' '' '' '' "$restart" >> /dev/null
|
||||
exit
|
||||
fi
|
||||
|
||||
# Adding top-level domain and then its sub
|
||||
$BIN/v-add-dns-domain "$user" "$top_domain" "$ip" '' '' '' '' '' '' '' '' "$restart" >> /dev/null
|
||||
|
||||
# Checking top-level domain
|
||||
if [ ! -e "$USER_DATA/dns/$top_domain.conf" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Checking subdomain record
|
||||
if [ "$sub_domain" == '*' ]; then
|
||||
check_record=$(grep -w "RECORD='\*'" $USER_DATA/dns/$top_domain.conf)
|
||||
else
|
||||
check_record=$(grep -w "RECORD='$sub_domain'" $USER_DATA/dns/$top_domain.conf)
|
||||
fi
|
||||
|
||||
# Adding subdomain record
|
||||
if [ -z "$check_record" ]; then
|
||||
$BIN/v-add-dns-record \
|
||||
"$user" "$top_domain" "$sub_domain" A "$ip" '' '' "$restart" >> /dev/null
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# No logging
|
||||
|
||||
exit
|
@ -0,0 +1,172 @@
|
||||
#!/bin/bash
|
||||
# info: add dns record
|
||||
# options: USER DOMAIN RECORD TYPE VALUE [PRIORITY] [ID] [RESTART] [TTL]
|
||||
#
|
||||
# example: v-add-dns-record admin acme.com www A 162.227.73.112
|
||||
#
|
||||
# This function is used to add a new DNS record. Complex records of TXT, MX and
|
||||
# SRV types can be used by a filling in the 'value' argument. This function also
|
||||
# gets an ID parameter for definition of certain record identifiers or for the
|
||||
# regulation of records.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
record=$(idn2 --quiet -d "$3")
|
||||
record=$(echo "$record" | tr '[:upper:]' '[:lower:]')
|
||||
rtype=$(echo "$4" | tr '[:lower:]' '[:upper:]')
|
||||
dvalue=$5
|
||||
priority=$6
|
||||
id=$7
|
||||
restart=$8
|
||||
ttl=$9
|
||||
quiet=${10}
|
||||
|
||||
if [ -z "$priority" ]; then
|
||||
priority=10
|
||||
fi
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/rebuild.sh
|
||||
source $HESTIA/func/rebuild.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Null priority for none MX/SRV records
|
||||
if [ "$rtype" != 'MX' ] && [ "$rtype" != 'SRV' ]; then
|
||||
priority=''
|
||||
fi
|
||||
|
||||
# Add trailing dot at the end of NS/CNAME/MX/PTR/SRV record
|
||||
if [[ $rtype =~ ^NS|CNAME|MX|PTR|SRV ]]; then
|
||||
trailing_dot=$(echo $dvalue | grep "\.$")
|
||||
if [ -z "$trailing_dot" ]; then
|
||||
dvalue="$dvalue."
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $rtype =~ ^NS|CNAME|MX|PTR|SRV ]]; then
|
||||
dvalue=$(idn2 --quiet "$dvalue")
|
||||
record=$(idn2 --quiet "$record")
|
||||
fi
|
||||
|
||||
# Cleanup quotes on dvalue
|
||||
# - [CAA] records will be left unchanged
|
||||
# - [SRV] will be stripped of double quotes even when containing spaces
|
||||
# - [DNSKEY] will be stripped of double quotes even when containing spaces
|
||||
# - Rest of record types will be striped of quotes and the final string
|
||||
# will be enclosed in double quotes if containing spaces or semicolons
|
||||
|
||||
if [ "$rtype" != "CAA" ]; then
|
||||
dvalue=${dvalue//\"/}
|
||||
# Add support for DS key
|
||||
if [ "$rtype" != "DNSKEY" ] && [ "$rtype" != "DS" ]; then
|
||||
if [ "$rtype" != 'SRV' ] && [[ "$dvalue" =~ [\;[:space:]] ]]; then
|
||||
dvalue='"'"$dvalue"'"'
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$record" = "@" ] && [ "$rtype" = "CNAME" ]; then
|
||||
check_result $E_INVALID "CNAME on root is not allowed"
|
||||
fi
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '5' "$#" 'USER DOMAIN RECORD TYPE VALUE [PRIORITY] [ID] [RESTART] [TTL]'
|
||||
is_format_valid 'user' 'domain' 'record' 'rtype' 'dvalue'
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'dns' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'dns' 'DOMAIN' "$domain"
|
||||
is_package_full 'DNS_RECORDS'
|
||||
get_next_dnsrecord
|
||||
is_format_valid 'id'
|
||||
is_object_new "dns/$domain" 'ID' "$id"
|
||||
is_dns_fqnd "$rtype" "$dvalue"
|
||||
is_dns_nameserver_valid "$domain" "$rtype" "$dvalue"
|
||||
is_format_valid 'ttl'
|
||||
if [ -n "$restart" ]; then
|
||||
is_format_valid 'restart'
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Adding record
|
||||
zone="$USER_DATA/dns/$domain.conf"
|
||||
dns_rec="ID='$id' RECORD='$record' TYPE='$rtype' PRIORITY='$priority'"
|
||||
dns_rec="$dns_rec VALUE='$dvalue' SUSPENDED='no' TIME='$time' DATE='$date'"
|
||||
[ -n "$ttl" ] && dns_rec="$dns_rec TTL='$ttl'"
|
||||
echo "$dns_rec" >> $zone
|
||||
chmod 660 $zone
|
||||
|
||||
# Sorting records
|
||||
sort_dns_records
|
||||
|
||||
# Update serial
|
||||
update_domain_serial
|
||||
# Updating zone
|
||||
if [[ "$DNS_SYSTEM" =~ named|bind ]]; then
|
||||
# Do full rebuild due DNS SEC
|
||||
rebuild_dns_domain_conf
|
||||
fi
|
||||
|
||||
# Updating dns-cluster queue
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
# Check for first sync
|
||||
dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe)
|
||||
if [ -z "$dlock" ]; then
|
||||
cmd="$BIN/v-add-remote-dns-record $user $domain $id"
|
||||
echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Update counters
|
||||
records="$(wc -l $USER_DATA/dns/$domain.conf | cut -f1 -d ' ')"
|
||||
update_object_value 'dns' 'DOMAIN' "$domain" '$RECORDS' "$records"
|
||||
increase_user_value "$user" '$U_DNS_RECORDS'
|
||||
|
||||
# Restart named
|
||||
$BIN/v-restart-dns "$restart"
|
||||
check_result $? "$E_RESTART" 'dns failed to restart'
|
||||
|
||||
# Logging
|
||||
if [ "$quiet" != "yes" ]; then
|
||||
$BIN/v-log-action "$user" "Info" "DNS" "Added DNS record (Type: $rtype, Value: $record, Domain: $domain)."
|
||||
fi
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,100 @@
|
||||
#!/bin/bash
|
||||
# info: add web/dns/mail domain
|
||||
# options: USER DOMAIN [IP] [RESTART]
|
||||
#
|
||||
# example: v-add-domain admin example.com
|
||||
#
|
||||
# This function adds web/dns/mail domain to a server.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
ip=$3
|
||||
restart=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
check_args '2' "$#" 'USER DOMAIN [IP] [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'restart'
|
||||
if [ -n "$ip" ]; then
|
||||
is_format_valid 'ip'
|
||||
fi
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Get ip if it wasn't defined
|
||||
if [ -z "$ip" ]; then
|
||||
get_user_ip
|
||||
if [ -z "$ip" ]; then
|
||||
check_result "$E_NOTEXIST" "no available IP address"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Working on web domain
|
||||
if [ -n "$WEB_SYSTEM" ]; then
|
||||
check1=$(is_package_full 'WEB_DOMAINS')
|
||||
if [ $? -eq 0 ]; then
|
||||
$BIN/v-add-web-domain "$user" "$domain" "$ip" 'no'
|
||||
check_result $? "can't add web domain"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Working on DNS domain
|
||||
if [ -n "$DNS_SYSTEM" ]; then
|
||||
check2=$(is_package_full 'DNS_DOMAINS')
|
||||
if [ $? -eq 0 ]; then
|
||||
$BIN/v-add-dns-domain "$user" "$domain" "$ip" "" "" "" "" "" "" "" "" "no"
|
||||
check_result $? "can't add dns domain"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Working on mail domain
|
||||
if [ -n "$MAIL_SYSTEM" ]; then
|
||||
check3=$(is_package_full 'MAIL_DOMAINS')
|
||||
if [ $? -eq 0 ]; then
|
||||
$BIN/v-add-mail-domain $user $domain 'no'
|
||||
check_result $? "can't add mail domain"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$check1" != '' && "$check2" != '' && "$check3" != '' ]]; then
|
||||
check_result 8 "Package limit reached"
|
||||
fi
|
||||
|
||||
# Restarting services
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "can't restart web" > /dev/null
|
||||
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "can't restart proxy" > /dev/null
|
||||
|
||||
$BIN/v-restart-dns "$restart"
|
||||
check_result $? "can't restart dns" > /dev/null
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
exit
|
@ -0,0 +1,118 @@
|
||||
#!/bin/bash
|
||||
# info: Enable FastCGI cache for nginx
|
||||
# options: USER DOMAIN [DURATION] [RESTART]
|
||||
#
|
||||
# example: v-add-fastcgi-cache user domain.tld 30m
|
||||
#
|
||||
# This function enables FastCGI cache for nginx
|
||||
# Acceptable values for duration is time in seconds (10s) minutes (10m) or days (10d)
|
||||
# Add "yes" as last parameter to restart nginx
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
duration=${3-2m}
|
||||
restart=${4-no}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN [DURATION] [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'restart'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
|
||||
if ! [[ "$duration" =~ ^[0-9].*[s|m|d]$ ]]; then
|
||||
echo "Invalid duration"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [[ "$duration" =~ ^[0].*[s|m|d]$ ]]; then
|
||||
echo "Invalid duration"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Load domain data
|
||||
parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf)
|
||||
|
||||
# Check that nginx is not in proxy mode
|
||||
if [ "$WEB_SYSTEM" != 'nginx' ]; then
|
||||
echo "Error: nginx is in proxy mode"
|
||||
exit "$E_NOTEXIST"
|
||||
fi
|
||||
|
||||
fastcgi="$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.fastcgi_cache.conf"
|
||||
no_cache='$no_cache'
|
||||
|
||||
cat << EOF > $fastcgi
|
||||
fastcgi_cache $domain;
|
||||
fastcgi_cache_valid 200 $duration;
|
||||
fastcgi_cache_valid 301 302 10m;
|
||||
fastcgi_cache_valid 404 10m;
|
||||
fastcgi_cache_bypass $no_cache;
|
||||
fastcgi_no_cache $no_cache;
|
||||
set $no_cache 0;
|
||||
EOF
|
||||
|
||||
chown root:$user $fastcgi
|
||||
chmod 640 $fastcgi
|
||||
|
||||
str="fastcgi_cache_path /var/cache/nginx/micro/$domain levels=1:2"
|
||||
str="$str keys_zone=$domain:10m max_size=512m inactive=30m use_temp_path=off;"
|
||||
conf='/etc/nginx/conf.d/fastcgi_cache_pool.conf'
|
||||
if [ -f "$conf" ]; then
|
||||
if [ -z "$(grep "=${domain}:" $conf)" ]; then
|
||||
echo "$str" >> $conf
|
||||
fi
|
||||
else
|
||||
echo "$str" >> $conf
|
||||
fi
|
||||
|
||||
mkdir -p /var/cache/nginx/micro/$domain
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ -z "$FASTCGI_CACHE" ]; then
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'FASTCGI_CACHE' 'ALIAS'
|
||||
fi
|
||||
if [ -z "$FASTCGI_DURATION" ]; then
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'FASTCGI_DURATION' 'ALIAS'
|
||||
fi
|
||||
|
||||
# Set FastCGI cache flag to enabled
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$FASTCGI_CACHE' 'yes'
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$FASTCGI_DURATION' "$duration"
|
||||
|
||||
# Restart web server
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "Web server restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "FastCGI cache enabled (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,91 @@
|
||||
#!/bin/bash
|
||||
# info: add firewall blocking rule
|
||||
# options: IP CHAIN
|
||||
#
|
||||
# example: v-add-firewall-ban 37.120.129.20 MAIL
|
||||
#
|
||||
# This function adds new blocking rule to system firewall
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
ip=$1
|
||||
chain=$(echo $2 | tr '[:lower:]' '[:upper:]')
|
||||
|
||||
# Defining absolute path for iptables and modprobe
|
||||
iptables="/sbin/iptables"
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/firewall.sh
|
||||
source $HESTIA/func/firewall.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'IP CHAIN'
|
||||
is_format_valid 'ip' 'chain'
|
||||
is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Self heal iptables links
|
||||
heal_iptables_links
|
||||
|
||||
# Checking server ip
|
||||
if [ -e "$HESTIA/data/ips/$ip" ] || [ "$ip" = '127.0.0.1' ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Checking ip exclusions
|
||||
excludes="$HESTIA/data/firewall/excludes.conf"
|
||||
check_excludes=$(grep "^$ip$" $excludes 2> /dev/null)
|
||||
if [ -n "$check_excludes" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Checking ip in banlist
|
||||
conf="$HESTIA/data/firewall/banlist.conf"
|
||||
check_ip=$(grep "IP='$ip' CHAIN='$chain'" $conf 2> /dev/null)
|
||||
if [ -n "$check_ip" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Adding chain
|
||||
$BIN/v-add-firewall-chain $chain
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Adding ip to banlist
|
||||
echo "IP='$ip' CHAIN='$chain' TIME='$time' DATE='$date'" >> $conf
|
||||
$iptables -I fail2ban-$chain 1 -s $ip \
|
||||
-j REJECT --reject-with icmp-port-unreachable 2> /dev/null
|
||||
|
||||
# Changing permissions
|
||||
chmod 660 $conf
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Warning" "Firewall" "Banned IP address $ip."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,130 @@
|
||||
#!/bin/bash
|
||||
# info: add firewall chain
|
||||
# options: CHAIN [PORT] [PROTOCOL] [PROTOCOL]
|
||||
#
|
||||
# example: v-add-firewall-chain CRM 5678 TCP
|
||||
#
|
||||
# This function adds new rule to system firewall
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
chain=$(echo $1 | tr '[:lower:]' '[:upper:]')
|
||||
port=$2
|
||||
port_ext=$2
|
||||
protocol=${4-TCP}
|
||||
protocol=$(echo $protocol | tr '[:lower:]' '[:upper:]')
|
||||
|
||||
# Defining absolute path to iptables
|
||||
iptables="/sbin/iptables"
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/firewall.sh
|
||||
source $HESTIA/func/firewall.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Get hestia port by reading nginx.conf
|
||||
hestiaport=$(grep -m 1 'listen' $HESTIA/nginx/conf/nginx.conf | awk '{print $2}' | sed "s|;||")
|
||||
if [ -z "$hestiaport" ]; then
|
||||
hestiaport=8083
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'CHAIN [PORT] [PROTOCOL]'
|
||||
is_format_valid 'chain' 'port_ext' 'protocol'
|
||||
is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Self heal iptables links
|
||||
heal_iptables_links
|
||||
|
||||
# Checking known chains
|
||||
case $chain in
|
||||
SSH) # Get ssh port by reading ssh config file.
|
||||
sshport=$(grep '^Port ' /etc/ssh/sshd_config | head -1 | cut -d ' ' -f 2)
|
||||
if [ -z "$sshport" ]; then
|
||||
sshport=22
|
||||
fi
|
||||
port=$sshport
|
||||
protocol=TCP
|
||||
;;
|
||||
FTP)
|
||||
port=21
|
||||
protocol=TCP
|
||||
;;
|
||||
MAIL)
|
||||
port='25,465,587,110,995,143,993'
|
||||
protocol=TCP
|
||||
;;
|
||||
DNS)
|
||||
port=53
|
||||
protocol=UDP
|
||||
;;
|
||||
WEB)
|
||||
port='80,443'
|
||||
protocol=TCP
|
||||
;;
|
||||
DB)
|
||||
port='3306,5432'
|
||||
protocol=TCP
|
||||
;;
|
||||
HESTIA)
|
||||
port=$hestiaport
|
||||
protocol=TCP
|
||||
;;
|
||||
RECIDIVE)
|
||||
port='1:65535'
|
||||
protocol=TCP
|
||||
;;
|
||||
*) check_args '2' "$#" 'CHAIN PORT' ;;
|
||||
esac
|
||||
|
||||
# Adding chain
|
||||
$iptables -N fail2ban-$chain 2> /dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
$iptables -A fail2ban-$chain -j RETURN
|
||||
|
||||
# Adding multiport module
|
||||
if [[ "$port" =~ ,|-|: ]]; then
|
||||
port_str="-m multiport --dports $port"
|
||||
else
|
||||
port_str="--dport $port"
|
||||
fi
|
||||
$iptables -I INPUT -p $protocol $port_str -j fail2ban-$chain
|
||||
fi
|
||||
|
||||
# Preserving chain
|
||||
chains=$HESTIA/data/firewall/chains.conf
|
||||
check_chain=$(grep "CHAIN='$chain'" $chains 2> /dev/null)
|
||||
if [ -z "$check_chain" ]; then
|
||||
echo "CHAIN='$chain' PORT='$port' PROTOCOL='$protocol'" >> $chains
|
||||
fi
|
||||
|
||||
# Changing permissions
|
||||
chmod 660 $chains
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "Firewall" "Added service to firewall (Service: $chain, Port: $port, Protocol: $protocol)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,205 @@
|
||||
#!/bin/bash
|
||||
# info: add firewall ipset
|
||||
# options: NAME [SOURCE] [IPVERSION] [AUTOUPDATE] [REFRESH]
|
||||
#
|
||||
# example: v-add-firewall-ipset country-nl "https://raw.githubusercontent.com/ipverse/rir-ip/master/country/nl/ipv4-aggregated.txt"
|
||||
#
|
||||
# This function adds new ipset to system firewall
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
ip_name=${1}
|
||||
data_source=${2}
|
||||
ip_version=${3:-v4}
|
||||
autoupdate=${4:-yes}
|
||||
refresh=${5:-no}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'NAME [SOURCE] [IPVERSION] [AUTOUPDATE] [FORCE]'
|
||||
is_format_valid 'ip_name'
|
||||
is_boolean_format_valid "$autoupdate" 'Automatically update IP list (yes/no)'
|
||||
is_boolean_format_valid "$refresh" 'Refresh IP list (yes/no)'
|
||||
is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
# Define variables for ipset configuration
|
||||
ipset_hstobject='../../data/firewall/ipset'
|
||||
IPSET_BIN="$(command -v ipset)"
|
||||
IPSET_PATH="$HESTIA/data/firewall/ipset"
|
||||
|
||||
# Ensure ipset is installed
|
||||
if [ -z "$IPSET_BIN" ]; then
|
||||
if [ -f '/etc/redhat-release' ]; then
|
||||
dnf install -q -y ipset > /dev/null
|
||||
else
|
||||
apt-get --quiet --yes install ipset > /dev/null
|
||||
fi
|
||||
check_result $? "Installing IPset package"
|
||||
|
||||
IPSET_BIN="$(which ipset)"
|
||||
check_result $? "IPset binary not found"
|
||||
fi
|
||||
|
||||
# Ensure ipset configuration path and master file exist before attempting to parse
|
||||
mkdir -p "$IPSET_PATH"
|
||||
if [ ! -f "$HESTIA/data/firewall/ipset.conf" ]; then
|
||||
touch $HESTIA/data/firewall/ipset.conf
|
||||
fi
|
||||
|
||||
if [ -z "$data_source" ]; then
|
||||
if [ ! -f "${IPSET_PATH}.conf" ] || [[ ! $(grep "LISTNAME='$ip_name'" "${IPSET_PATH}.conf") ]]; then
|
||||
check_args '2' "$#" 'NAME SOURCE [IPVERSION] [AUTOUPDATE] [FORCE]'
|
||||
fi
|
||||
|
||||
data_source="$(get_object_value "$ipset_hstobject" 'LISTNAME' "$ip_name" '$SOURCE')"
|
||||
ip_version="$(get_object_value "$ipset_hstobject" 'LISTNAME' "$ip_name" '$IP_VERSION')"
|
||||
else
|
||||
is_object_new "$ipset_hstobject" 'LISTNAME' "$ip_name"
|
||||
fi
|
||||
|
||||
if [ "$ip_version" != "v4" ] && [ "$ip_version" != "v6" ]; then
|
||||
check_result "$E_INVALID" "invalid ip version, valid: (v4|v6)"
|
||||
fi
|
||||
|
||||
if ! echo "$data_source" | egrep -q '^(https?|script|file):'; then
|
||||
check_result "$E_INVALID" "invalid ipset source, valid: (http[s]://|script:|file:)"
|
||||
fi
|
||||
|
||||
IPSET_FILE="${ip_name}.${ip_version}"
|
||||
IPSET_MIN_SIZE=10
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generate ip lists file if missing or required refresh
|
||||
if [ ! -f "${IPSET_PATH}/${IPSET_FILE}.iplist" ] || [ "$refresh" = "yes" ]; then
|
||||
|
||||
iplist_tempfile=$(mktemp)
|
||||
|
||||
if [[ "$data_source" =~ ^https?:// ]]; then
|
||||
|
||||
wget --tries=3 --timeout=15 --read-timeout=15 --waitretry=3 --no-dns-cache --quiet "$data_source" -O "$iplist_tempfile"
|
||||
check_result $? "Downloading ip list"
|
||||
|
||||
# Advanced: execute script with the same basename for aditional pre-processing
|
||||
# ex:
|
||||
if [ -x "${IPSET_PATH}/${IPSET_FILE}.sh" ]; then
|
||||
if [ -e '/etc/redhat-release' ]; then
|
||||
preprocess_output="$(cat "$iplist_tempfile" | setpriv --clear-groups --reuid nobody --regid nobody -- ${IPSET_PATH}/${IPSET_FILE}.sh "$ip_name" "$iplist_tempfile")"
|
||||
else
|
||||
preprocess_output="$(cat "$iplist_tempfile" | setpriv --clear-groups --reuid nobody --regid nogroup -- ${IPSET_PATH}/${IPSET_FILE}.sh "$ip_name" "$iplist_tempfile")"
|
||||
fi
|
||||
check_result $? "Preprocessing script failed (${IPSET_FILE}.sh)"
|
||||
[[ "$preprocess_output" ]] && echo "$preprocess_output" > "$iplist_tempfile"
|
||||
fi
|
||||
|
||||
elif [[ "$data_source" =~ ^script:/ ]]; then
|
||||
|
||||
# Generate the ip list file trough a external script
|
||||
# ex: compiling a ip list from multiple sources on demand
|
||||
if [ -x "${data_source#script:}" ]; then
|
||||
if [ -e '/etc/redhat-release' ]; then
|
||||
setpriv --clear-groups --reuid nobody --regid nobody -- ${data_source#script:} "$ip_name" > "$iplist_tempfile"
|
||||
else
|
||||
setpriv --clear-groups --reuid nobody --regid nogroup -- ${data_source#script:} "$ip_name" > "$iplist_tempfile"
|
||||
fi
|
||||
check_result $? "Running custom ip list update script"
|
||||
|
||||
fi
|
||||
|
||||
elif [[ "$data_source" =~ ^file:/ ]]; then
|
||||
|
||||
# Use a external ip-list file managed by other apps
|
||||
# ex: Using a ip list that is continuously updated
|
||||
[ -f "${data_source#file:}" ] && cp -f "${data_source#file:}" "$iplist_tempfile"
|
||||
|
||||
fi
|
||||
|
||||
# Cleanup ip list
|
||||
sed -r -i -e 's/[;#].*$//' -e 's/[ \t]*$//' -e '/^$/d' "$iplist_tempfile"
|
||||
if [[ $ip_version == 'v4' ]]; then
|
||||
sed -i -r -n -e '/^((1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])/p' "$iplist_tempfile"
|
||||
elif [[ $ip_version == 'v6' ]]; then
|
||||
sed -i -r -n -e '/^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}/p' "$iplist_tempfile"
|
||||
fi
|
||||
|
||||
# Validate iplist file size
|
||||
iplist_size=$(sed -r -e '/^#|^$/d' "$iplist_tempfile" | wc -l)
|
||||
[[ "$iplist_size" -le "$IPSET_MIN_SIZE" ]] && check_result "$E_INVALID" "IP list file too small (<${IPSET_MIN_SIZE}), ignoring"
|
||||
mv -f "$iplist_tempfile" "${IPSET_PATH}/${IPSET_FILE}.iplist"
|
||||
|
||||
fi
|
||||
|
||||
# Load ipset in kernel
|
||||
inet_ver="inet"
|
||||
[ "$ip_version" == "v6" ] && inet_ver="inet6"
|
||||
|
||||
$IPSET_BIN -quiet create -exist "$ip_name" hash:net family $inet_ver
|
||||
$IPSET_BIN -quiet destroy "${ip_name}-tmp"
|
||||
$IPSET_BIN create "${ip_name}-tmp" -exist hash:net family $inet_ver maxelem 1048576
|
||||
$IPSET_BIN flush "${ip_name}-tmp"
|
||||
|
||||
sed -rn -e '/^#|^$/d' -e "s/^(.*)/add ${ip_name}-tmp \\1/p" "${IPSET_PATH}/${IPSET_FILE}.iplist" | $IPSET_BIN -quiet restore
|
||||
check_result $? "Populating ipset table"
|
||||
|
||||
$IPSET_BIN swap "${ip_name}-tmp" "${ip_name}"
|
||||
$IPSET_BIN -quiet destroy "${ip_name}-tmp"
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
if [ ! -f "${IPSET_PATH}.conf" ] || [ -z "$(get_object_value "$ipset_hstobject" 'LISTNAME' "$ip_name" '$LISTNAME')" ]; then
|
||||
|
||||
# Concatenating rule
|
||||
str="LISTNAME='$ip_name' IP_VERSION='$ip_version' SOURCE='$data_source'"
|
||||
str="$str AUTOUPDATE='$autoupdate' SUSPENDED='no'"
|
||||
str="$str TIME='$time' DATE='$date'"
|
||||
echo "$str" >> $HESTIA/data/firewall/ipset.conf
|
||||
log_type="added"
|
||||
|
||||
elif [ "$refresh" = "yes" ]; then
|
||||
|
||||
# Update iplist last regen time
|
||||
update_object_value "$ipset_hstobject" 'LISTNAME' "$ip_name" '$TIME' "$time"
|
||||
update_object_value "$ipset_hstobject" 'LISTNAME' "$ip_name" '$DATE' "$date"
|
||||
log_type="refreshed"
|
||||
|
||||
fi
|
||||
|
||||
# Changing permissions
|
||||
chmod 660 $HESTIA/data/firewall/ipset.conf
|
||||
chmod 660 "${IPSET_PATH}/${IPSET_FILE}.iplist"
|
||||
|
||||
# Install ipset daily cron updater
|
||||
if ! grep --silent --no-messages "v-update-firewall-ipset" $HESTIA/data/queue/daily.pipe; then
|
||||
cmd="$BIN/v-update-firewall-ipset yes"
|
||||
echo "$cmd" >> $HESTIA/data/queue/daily.pipe
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "Firewall" "IPset IP list ${log_type:-loaded} (Name: $ip_name, IP version: $ip_version, Autoupdate: $autoupdate)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,109 @@
|
||||
#!/bin/bash
|
||||
# info: add firewall rule
|
||||
# options: ACTION IP PORT [PROTOCOL] [COMMENT] [RULE]
|
||||
#
|
||||
# example: v-add-firewall-rule DROP 185.137.111.77 25
|
||||
#
|
||||
# This function adds new rule to system firewall
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
action=$(echo $1 | tr '[:lower:]' '[:upper:]')
|
||||
ip=$2
|
||||
port_ext=$3
|
||||
protocol=${4-TCP}
|
||||
protocol=$(echo $protocol | tr '[:lower:]' '[:upper:]')
|
||||
comment=$5
|
||||
rule=$6
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Get next firewall rule id
|
||||
get_next_fw_rule() {
|
||||
if [ -z "$rule" ]; then
|
||||
curr_str=$(grep "RULE=" $HESTIA/data/firewall/rules.conf \
|
||||
| cut -f 2 -d \' | sort -n | tail -n1)
|
||||
rule="$((curr_str + 1))"
|
||||
fi
|
||||
}
|
||||
|
||||
sort_fw_rules() {
|
||||
cat $HESTIA/data/firewall/rules.conf \
|
||||
| sort -n -k 2 -t \' > $HESTIA/data/firewall/rules.conf.tmp
|
||||
mv -f $HESTIA/data/firewall/rules.conf.tmp \
|
||||
$HESTIA/data/firewall/rules.conf
|
||||
}
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'ACTION IP PORT [PROTOCOL] [COMMENT] [RULE]'
|
||||
is_format_valid 'action' 'protocol' 'port_ext'
|
||||
is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM'
|
||||
get_next_fw_rule
|
||||
is_format_valid 'rule'
|
||||
is_object_new '../../data/firewall/rules' 'RULE' "$rule"
|
||||
if [ -n "$comment" ]; then
|
||||
is_format_valid 'comment'
|
||||
fi
|
||||
if [[ "$ip" =~ ^ipset: ]]; then
|
||||
ipset_name="${ip#ipset:}"
|
||||
$BIN/v-list-firewall-ipset plain | grep "^$ipset_name\s" > /dev/null
|
||||
check_result $? 'ipset object not found' "$E_NOTEXIST"
|
||||
else
|
||||
is_format_valid 'ip'
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Concatenating rule
|
||||
str="RULE='$rule' ACTION='$action' PROTOCOL='$protocol' PORT='$port_ext'"
|
||||
str="$str IP='$ip' COMMENT='$comment' SUSPENDED='no'"
|
||||
str="$str TIME='$time' DATE='$date'"
|
||||
|
||||
# Adding to config
|
||||
echo "$str" >> $HESTIA/data/firewall/rules.conf
|
||||
|
||||
# Changing permissions
|
||||
chmod 660 $HESTIA/data/firewall/rules.conf
|
||||
|
||||
# Sorting firewall rules by id number
|
||||
sort_fw_rules
|
||||
|
||||
# Updating system firewall
|
||||
$BIN/v-update-firewall
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Fix missing port value in log if zero
|
||||
if [ -z "$port" ]; then
|
||||
port="0"
|
||||
fi
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "Firewall" "Added firewall rule (Action: $action, Port: $port, Protocol: $protocol)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,85 @@
|
||||
#!/bin/bash
|
||||
# info: archive directory
|
||||
# options: USER ARCHIVE SOURCE [SOURCE...]
|
||||
#
|
||||
# example: v-add-fs-archive admin archive.tar readme.txt
|
||||
#
|
||||
# This function creates tar archive
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
user=$1
|
||||
archive=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER ARCHIVE FILE [FILE_2] [FILE_3] [FILE ...]'
|
||||
is_format_valid 'user'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
# Checking user homedir
|
||||
homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :)
|
||||
if [ -z "$homedir" ]; then
|
||||
echo "Error: user home directory doesn't exist"
|
||||
exit 12
|
||||
fi
|
||||
|
||||
# Checking archive
|
||||
if [ -e "$archive" ]; then
|
||||
echo "Error: archive already exist $archive"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Checking source path
|
||||
IFS=$'\n'
|
||||
i=1
|
||||
for src in $*; do
|
||||
if [ "$i" -gt 2 ]; then
|
||||
rpath=$(readlink -f "$src")
|
||||
if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then
|
||||
echo "Error: invalid source path $src"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
((i++))
|
||||
done
|
||||
|
||||
i=1
|
||||
for src in $*; do
|
||||
if [ "$i" -gt 2 ]; then
|
||||
# Deleting leading home path
|
||||
src=$(echo "$src" | sed -e "s|/home/$user/||")
|
||||
|
||||
# Creating tar.gz archive
|
||||
user_exec tar -rf "${archive/.gz/}" -C /home/$user $src > /dev/null 2>&1
|
||||
if [ "$?" -ne 0 ]; then
|
||||
echo "Error: archive $archive was not created"
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
((i++))
|
||||
done
|
||||
|
||||
# Checking gzip
|
||||
if [[ "$archive" =~ \.gz$ ]]; then
|
||||
user_exec gzip "${archive/.gz/}" > /dev/null 2>&1
|
||||
if [ "$?" -ne 0 ]; then
|
||||
echo "Error: archive $archive was not gziped"
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
|
||||
exit
|
@ -0,0 +1,55 @@
|
||||
#!/bin/bash
|
||||
# info: add directory
|
||||
# options: USER DIRECTORY
|
||||
#
|
||||
# example: v-add-fs-directory admin mybar
|
||||
#
|
||||
# This function creates new directory on the file system
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
user=$1
|
||||
dst_dir=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DIR'
|
||||
is_format_valid 'user'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
# Checking user homedir
|
||||
homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :)
|
||||
if [ -z "$homedir" ]; then
|
||||
echo "Error: user home directory doesn't exist"
|
||||
exit 12
|
||||
fi
|
||||
|
||||
# Checking destination path
|
||||
rpath=$(readlink -f "$dst_dir")
|
||||
if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then
|
||||
echo "Error: invalid destination path $dst_dir"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Adding directory
|
||||
user_exec mkdir -p "$dst_dir" > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error: directory $dst_dir was not created"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
# Exiting
|
||||
exit
|
@ -0,0 +1,55 @@
|
||||
#!/bin/bash
|
||||
# info: add file
|
||||
# options: USER FILE
|
||||
#
|
||||
# example: v-add-fs-file admin readme.md
|
||||
#
|
||||
# This function creates new files on file system
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
user=$1
|
||||
dst_file=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER FILE'
|
||||
is_format_valid 'user'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
# Checking user homedir
|
||||
homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :)
|
||||
if [ -z $homedir ]; then
|
||||
echo "Error: user home directory doesn't exist"
|
||||
exit 12
|
||||
fi
|
||||
|
||||
# Checking destination path
|
||||
rpath=$(readlink -f "$dst_file")
|
||||
if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then
|
||||
echo "Error: invalid destination path $dst_file"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Creating file
|
||||
user_exec touch "$dst_file" > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error: file $dst_file was not created"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
# Exiting
|
||||
exit
|
@ -0,0 +1,629 @@
|
||||
#!/bin/bash
|
||||
# info: check letsencrypt domain
|
||||
# options: USER DOMAIN [ALIASES] [MAIL]
|
||||
#
|
||||
# example: v-add-letsencrypt-domain admin wonderland.com www.wonderland.com,demo.wonderland.com
|
||||
# example: v-add-letsencrypt-domain admin wonderland.com '' yes
|
||||
#
|
||||
# This function check and validates domain with Let's Encrypt
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
aliases=$3
|
||||
mail=${4// /}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# LE API
|
||||
LE_API='https://acme-v02.api.letsencrypt.org'
|
||||
|
||||
if [[ "$LE_STAGING" = 'yes' ]]; then
|
||||
LE_API='https://acme-staging-v02.api.letsencrypt.org'
|
||||
fi
|
||||
|
||||
# encode base64
|
||||
encode_base64() {
|
||||
cat | base64 | tr '+/' '-_' | tr -d '\r\n='
|
||||
}
|
||||
|
||||
# Let's Encrypt v2 curl function
|
||||
query_le_v2() {
|
||||
protected='{"nonce": "'$3'",'
|
||||
protected=''$protected' "url": "'$1'",'
|
||||
protected=''$protected' "alg": "RS256", "kid": "'$KID'"}'
|
||||
content="Content-Type: application/jose+json"
|
||||
|
||||
payload_=$(echo -n "$2" | encode_base64)
|
||||
protected_=$(echo -n "$protected" | encode_base64)
|
||||
signature_=$(printf "%s" "$protected_.$payload_" \
|
||||
| openssl dgst -sha256 -binary -sign $USER_DATA/ssl/user.key \
|
||||
| encode_base64)
|
||||
|
||||
post_data='{"protected":"'"$protected_"'",'
|
||||
post_data=$post_data'"payload":"'"$payload_"'",'
|
||||
post_data=$post_data'"signature":"'"$signature_"'"}'
|
||||
|
||||
# Save http response to file passed as "$4" arg or print to stdout if not provided
|
||||
# http response headers are always sent to stdout
|
||||
local save_to_file=${4:-"/dev/stdout"}
|
||||
curl --location --user-agent "HestiaCP" --insecure --retry 5 --retry-connrefused --silent --dump-header /dev/stdout --data "$post_data" "$1" --header "$content" --output "$save_to_file"
|
||||
debug_log "API call" "exit status: $?"
|
||||
}
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN [ALIASES] [MAIL]'
|
||||
is_format_valid 'user' 'domain' 'aliases'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
if [ -n "$mail" ]; then
|
||||
is_boolean_format_valid "$mail" 'mail'
|
||||
fi
|
||||
|
||||
# Set DNS CAA record retrieval commands
|
||||
if [ -n "$DNS_SYSTEM" ]; then
|
||||
dns_domain=$($BIN/v-list-dns-domains "$user" | grep "$domain" | cut -d' ' -f1)
|
||||
caa_record=$($BIN/v-list-dns-records "$user" "$domain" | grep -i "CAA" | grep -i "letsencrypt.org" | cut -d' ' -f1)
|
||||
fi
|
||||
|
||||
if [ -z "$mail" ] || [ "$mail" = 'no' ]; then
|
||||
mail=''
|
||||
is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
get_domain_values 'web'
|
||||
# check if alias is the letsencrypt wildcard domain, if not, make the normal checks
|
||||
if [[ "$aliases" != "*.$domain" ]]; then
|
||||
for alias in $(echo "$aliases" | tr ',' '\n' | sort -u); do
|
||||
check_alias="$(echo $ALIAS | tr ',' '\n' | grep ^$alias$)"
|
||||
if [ -z "$check_alias" ]; then
|
||||
check_result "$E_NOTEXIST" "domain alias $alias doesn't exist"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
else
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
fi
|
||||
|
||||
# Dump debug info
|
||||
debug_log() {
|
||||
echo -e "\n==[${1}]==\n${2}\n" >> "$log_file"
|
||||
}
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generate correct variables for mail domain SSL certificates
|
||||
if [ -n "$mail" ]; then
|
||||
root_domain=$domain
|
||||
domain="mail.$root_domain"
|
||||
webmail=$(get_object_value "mail" "DOMAIN" "$root_domain" '$WEBMAIL')
|
||||
if [ -n "$webmail" ]; then
|
||||
aliases="$WEBMAIL_ALIAS.$root_domain"
|
||||
fi
|
||||
else
|
||||
parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf)
|
||||
|
||||
domain_redirect="$REDIRECT"
|
||||
if [[ -n "$domain_redirect" ]]; then
|
||||
domain_redirect_code="$REDIRECT_CODE"
|
||||
$BIN/v-delete-web-domain-redirect $user $domain
|
||||
fi
|
||||
|
||||
domain_forcessl="$SSL_FORCE"
|
||||
if [[ "$domain_forcessl" == 'yes' ]]; then
|
||||
$BIN/v-delete-web-domain-ssl-force $user $domain
|
||||
fi
|
||||
fi
|
||||
|
||||
log_file="/var/log/hestia/LE-${user}-${domain}.log"
|
||||
touch "$log_file"
|
||||
chmod 600 "$log_file"
|
||||
|
||||
echo -e "\n\n=============================
|
||||
Date Time: $(date +%Y-%m-%d) $(date +%H:%M:%S)
|
||||
WEB_SYSTEM: ${WEB_SYSTEM}
|
||||
PROXY_SYSTEM: ${PROXY_SYSTEM}
|
||||
user: ${user}
|
||||
domain: ${domain}
|
||||
" >> "$log_file"
|
||||
|
||||
# Registering LetsEncrypt user account
|
||||
$BIN/v-add-letsencrypt-user $user
|
||||
if [ "$?" -ne 0 ]; then
|
||||
touch $HESTIA/data/queue/letsencrypt.pipe
|
||||
sed -i "/ $domain /d" $HESTIA/data/queue/letsencrypt.pipe
|
||||
send_notice "LETSENCRYPT" "Account registration failed ($user)"
|
||||
check_result "$E_CONNECT" "LE account registration ($user)" > /dev/null
|
||||
fi
|
||||
|
||||
# Parsing LetsEncrypt account data
|
||||
source $USER_DATA/ssl/le.conf
|
||||
|
||||
# Checking wildcard alias
|
||||
if [ "$aliases" = "*.$domain" ]; then
|
||||
wildcard='yes'
|
||||
proto="dns-01"
|
||||
if [ ! -e "$HESTIA/data/users/$user/dns/$domain.conf" ]; then
|
||||
check_result "$E_NOTEXIST" "DNS domain $domain doesn't exist"
|
||||
fi
|
||||
else
|
||||
proto="http-01"
|
||||
fi
|
||||
|
||||
echo -e "
|
||||
- aliases: ${aliases}
|
||||
- proto: ${proto}
|
||||
- wildcard: ${wildcard}
|
||||
" >> "$log_file"
|
||||
|
||||
# Check if dns records exist for requested domain/aliases
|
||||
if [ "$proto" = "http-01" ]; then
|
||||
for identifier in $(echo $domain,$aliases | tr ',' '\n' | sort -u); do
|
||||
if [[ "$identifier" = *[![:ascii:]]* ]]; then
|
||||
identifier=$(idn2 --quiet $identifier)
|
||||
fi
|
||||
if ! nslookup "${identifier}" > /dev/null 2>&1; then
|
||||
# Attempt against Cloudflare DNS
|
||||
if ! nslookup "${identifier}" 1.1.1.1 > /dev/null 2>&1; then
|
||||
check_result "$E_NOTEXIST" "DNS record for $identifier doesn't exist"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Ensure DNS CAA record exists for Let's Encrypt before requesting certificate
|
||||
if [ -n "$DNS_SYSTEM" ]; then
|
||||
# Check for DNS zone
|
||||
if [ "$dns_domain" = "$domain" ]; then
|
||||
# Replace DNS domain CAA records with Let's Encrypt values
|
||||
if [ -z "$caa_record" ]; then
|
||||
$BIN/v-add-dns-record "$user" "$domain" '@' 'CAA' '0 issue "letsencrypt.org"'
|
||||
else
|
||||
$BIN/v-delete-dns-record "$user" "$domain" "$caa_record"
|
||||
$BIN/v-add-dns-record "$user" "$domain" '@' 'CAA' '0 issue "letsencrypt.org"'
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Requesting nonce / STEP 1
|
||||
answer=$(curl --user-agent "HestiaCP" -s -I "$LE_API/directory")
|
||||
nonce=$(echo "$answer" | grep -i nonce | cut -f2 -d \ | tr -d '\r\n')
|
||||
status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f 2 -d ' ')
|
||||
|
||||
debug_log "Step 1" "- status: ${status}\n- nonce: ${nonce}\n- answer: ${answer}"
|
||||
|
||||
if [[ "$status" -ne 200 ]]; then
|
||||
# Delete DNS CAA record
|
||||
if [ -n "$DNS_SYSTEM" ]; then
|
||||
if [ "$dns_domain" = "$domain" ]; then
|
||||
if [ -n "$caa_record" ]; then
|
||||
$BIN/v-delete-dns-record "$user" "$domain" "$caa_record"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
check_result "$E_CONNECT" "Let's Encrypt nonce request status $status ($domain)"
|
||||
fi
|
||||
|
||||
# Placing new order / STEP 2
|
||||
url="$LE_API/acme/new-order"
|
||||
payload='{"identifiers":['
|
||||
for identifier in $(echo $domain,$aliases | tr ',' '\n' | sort -u); do
|
||||
if [[ "$identifier" = *[![:ascii:]]* ]]; then
|
||||
identifier=$(idn2 --quiet $identifier)
|
||||
fi
|
||||
payload=$payload'{"type":"dns","value":"'$identifier'"},'
|
||||
done
|
||||
payload=$(echo "$payload" | sed "s/,$//")
|
||||
payload=$payload']}'
|
||||
answer=$(query_le_v2 "$url" "$payload" "$nonce")
|
||||
nonce=$(echo "$answer" | grep -i nonce | cut -f2 -d \ | tr -d '\r\n')
|
||||
authz=$(echo "$answer" | grep "acme/authz" | cut -f2 -d '"')
|
||||
finalize=$(echo "$answer" | grep 'finalize":' | cut -f4 -d '"')
|
||||
status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f2 -d ' ')
|
||||
order=$(echo -e "$answer" | grep -i location | cut -f2 -d \ | tr -d '\r\n')
|
||||
|
||||
debug_log "Step 2" "- status: ${status}\n- nonce: ${nonce}\n- authz: ${authz}\n- finalize: ${finalize}\n- payload: ${payload}\n- answer: ${answer}\n order: ${order}"
|
||||
|
||||
if [[ "$status" -ne 201 ]]; then
|
||||
# Delete DNS CAA record
|
||||
if [ -n "$DNS_SYSTEM" ]; then
|
||||
if [ "$dns_domain" = "$domain" ]; then
|
||||
if [ -n "$caa_record" ]; then
|
||||
$BIN/v-delete-dns-record "$user" "$domain" "$caa_record"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
check_result $E_CONNECT "Let's Encrypt new auth status $status ($domain)"
|
||||
fi
|
||||
|
||||
# Requesting authorization token / STEP 3
|
||||
for auth in $authz; do
|
||||
payload=''
|
||||
answer=$(query_le_v2 "$auth" "$payload" "$nonce")
|
||||
url=$(echo "$answer" | grep -A3 $proto | grep -m1 url | cut -f 4 -d \")
|
||||
token=$(echo "$answer" | grep -A3 $proto | grep token | cut -f 4 -d \")
|
||||
nonce=$(echo "$answer" | grep -i nonce | cut -f2 -d \ | tr -d '\r\n')
|
||||
status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f 2 -d ' ')
|
||||
|
||||
debug_log "Step 3" "- status: ${status}\n- nonce: ${nonce}\n- url: ${url}\n- token: ${token}\n- answer: ${answer}"
|
||||
|
||||
if [[ "$status" -ne 200 ]]; then
|
||||
# Delete DNS CAA record
|
||||
if [ -n "$DNS_SYSTEM" ]; then
|
||||
dns_domain=$($BIN/v-list-dns-domains "$user" | grep "$domain" | cut -d' ' -f1)
|
||||
caa_record=$($BIN/v-list-dns-records "$user" "$domain" | grep -i "letsencrypt" | cut -d' ' -f1)
|
||||
|
||||
if [ "$dns_domain" = "$domain" ]; then
|
||||
if [ -n "$caa_record" ]; then
|
||||
$BIN/v-delete-dns-record "$user" "$domain" "$caa_record"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
check_result "$E_CONNECT" "Let's Encrypt acme/authz bad status $status ($domain)"
|
||||
fi
|
||||
|
||||
# Accepting challenge / STEP 4
|
||||
if [ "$wildcard" = 'yes' ]; then
|
||||
record=$(printf "%s" "$token.$THUMB" \
|
||||
| openssl dgst -sha256 -binary | encode_base64)
|
||||
old_records=$($BIN/v-list-dns-records "$user" "$domain" plain | grep 'TXT')
|
||||
old_records=$(echo "$old_records" | grep _acme-challenge | cut -f 1)
|
||||
for old_record in $old_records; do
|
||||
$BIN/v-delete-dns-record "$user" "$domain" "$old_record"
|
||||
done
|
||||
$BIN/v-add-dns-record "$user" "$domain" "_acme-challenge" "TXT" "$record"
|
||||
check_result $? "DNS _acme-challenge record wasn't created ($domain)"
|
||||
else
|
||||
if [ -z "$mail" ]; then
|
||||
if [ "$WEB_SYSTEM" = 'nginx' ] || [ "$PROXY_SYSTEM" = 'nginx' ]; then
|
||||
conf="$HOMEDIR/$user/conf/web/$domain/nginx.conf_letsencrypt"
|
||||
sconf="$HOMEDIR/$user/conf/web/$domain/nginx.ssl.conf_letsencrypt"
|
||||
echo 'location ~ "^/\.well-known/acme-challenge/([-_A-Za-z0-9]+)$" {' \
|
||||
> $conf
|
||||
echo ' default_type text/plain;' >> $conf
|
||||
echo ' return 200 "$1.'$THUMB'";' >> $conf
|
||||
echo '}' >> $conf
|
||||
if [ ! -e "$sconf" ]; then
|
||||
ln -s "$conf" "$sconf"
|
||||
fi
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
$BIN/v-restart-proxy
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
fi
|
||||
else
|
||||
# Get root directory from configuration
|
||||
domain_config="$HOMEDIR/$user/conf/web/$domain"
|
||||
if [ -f "$domain_config/apache2.conf" ]; then
|
||||
well_known="$(cat $domain_config/apache2.conf | egrep \
|
||||
'^\s+DocumentRoot' | awk '{split($0, a, " "); \
|
||||
print a[2]}')/.well-known"
|
||||
else
|
||||
well_known="$(cat $domain_config/nginx.conf | egrep '^\s+root' \
|
||||
| awk '{split($0, a, " "); print a[2]}' \
|
||||
| sed 's/;$//')/.well-known"
|
||||
fi
|
||||
acme_challenge="$well_known/acme-challenge"
|
||||
mkdir -p $acme_challenge
|
||||
echo "$token.$THUMB" > $acme_challenge/$token
|
||||
chown -R $user:$user $well_known
|
||||
fi
|
||||
else
|
||||
if [ "$WEB_SYSTEM" = 'nginx' ] || [ "$PROXY_SYSTEM" = 'nginx' ]; then
|
||||
conf="$HOMEDIR/$user/conf/mail/$root_domain/nginx.conf_letsencrypt"
|
||||
sconf="$HOMEDIR/$user/conf/mail/$root_domain/nginx.ssl.conf_letsencrypt"
|
||||
echo 'location ~ "^/\.well-known/acme-challenge/([-_A-Za-z0-9]+)$" {' \
|
||||
> $conf
|
||||
echo ' default_type text/plain;' >> $conf
|
||||
echo ' return 200 "$1.'$THUMB'";' >> $conf
|
||||
echo '}' >> $conf
|
||||
if [ ! -e "$sconf" ]; then
|
||||
ln -s "$conf" "$sconf"
|
||||
fi
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
$BIN/v-restart-proxy
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
fi
|
||||
else
|
||||
get_object_value 'mail' 'DOMAIN' "$root_domain" "WEBMAIL"
|
||||
if [ -n "$WEBMAIL" ]; then
|
||||
well_known="/var/lib/$WEBMAIL/.well-known"
|
||||
acme_challenge="$well_known/acme-challenge"
|
||||
mkdir -p $acme_challenge
|
||||
echo "$token.$THUMB" > $acme_challenge/$token
|
||||
chown -R $user:$user $well_known
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [ "$WEB_SYSTEM" = 'nginx' ]; then
|
||||
$BIN/v-restart-web
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
$BIN/v-update-sys-queue dns-cluster
|
||||
fi
|
||||
|
||||
# Requesting ACME validation / STEP 5
|
||||
validation_check=$(echo "$answer" | grep '"valid"')
|
||||
if [[ -n "$validation_check" ]]; then
|
||||
validation='valid'
|
||||
else
|
||||
validation='pending'
|
||||
sleep 5
|
||||
fi
|
||||
|
||||
# Doing pol check on status
|
||||
i=1
|
||||
while [ "$validation" = 'pending' ]; do
|
||||
payload='{}'
|
||||
answer=$(query_le_v2 "$url" "$payload" "$nonce")
|
||||
validation=$(echo "$answer" | grep -A1 $proto | tail -n1 | cut -f4 -d \")
|
||||
nonce=$(echo "$answer" | grep -i nonce | cut -f2 -d \ | tr -d '\r\n')
|
||||
status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f 2 -d ' ')
|
||||
details=$(echo "$answer" | grep detail | cut -f 1 -d ',' | cut -f 2-4 -d ':' | cut -f 2 -d '"')
|
||||
|
||||
debug_log "Step 5" "- status: ${status}\n- url: ${url}\n- nonce: ${nonce}\n- validation: ${validation}\n- details: ${details}\n- answer: ${answer}"
|
||||
|
||||
if [[ "$status" -ne 200 ]]; then
|
||||
# Delete DNS CAA record
|
||||
if [ -n "$DNS_SYSTEM" ]; then
|
||||
dns_domain=$($BIN/v-list-dns-domains "$user" | grep "$domain" | cut -d' ' -f1)
|
||||
caa_record=$($BIN/v-list-dns-records "$user" "$domain" | grep -i "letsencrypt" | cut -d' ' -f1)
|
||||
|
||||
if [ "$dns_domain" = "$domain" ]; then
|
||||
if [ -n "$caa_record" ]; then
|
||||
$BIN/v-delete-dns-record "$user" "$domain" "$caa_record"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
# Download debug info from LE server
|
||||
result=$(wget -qO- $url)
|
||||
debug_log "Debug information Step 5" "$result"
|
||||
details=$(echo $result | jq '.error.detail')
|
||||
error_code=$(echo $result | jq '.error.status')
|
||||
|
||||
debug_log "Abort Step 5" "=> Wrong status"
|
||||
check_result "$E_CONNECT" "Let's Encrypt validation status $status ($domain). Details: $error_code:$details"
|
||||
fi
|
||||
|
||||
i=$((i + 1))
|
||||
if [ "$i" -gt 10 ]; then
|
||||
# Delete DNS CAA record
|
||||
if [ -n "$DNS_SYSTEM" ]; then
|
||||
dns_domain=$($BIN/v-list-dns-domains "$user" | grep "$domain" | cut -d' ' -f1)
|
||||
caa_record=$($BIN/v-list-dns-records "$user" "$domain" | grep -i "letsencrypt" | cut -d' ' -f1)
|
||||
|
||||
if [ "$dns_domain" = "$domain" ]; then
|
||||
if [ -n "$caa_record" ]; then
|
||||
$BIN/v-delete-dns-record "$user" "$domain" "$caa_record"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
debug_log "Abort Step 5" "=> Too many validation retries"
|
||||
check_result "$E_CONNECT" "Let's Encrypt domain validation timeout ($domain)"
|
||||
fi
|
||||
sleep $((i * 2))
|
||||
done
|
||||
if [ "$validation" = 'invalid' ]; then
|
||||
# Delete DNS CAA record
|
||||
if [ -n "$DNS_SYSTEM" ]; then
|
||||
dns_domain=$($BIN/v-list-dns-domains "$user" | grep "$domain" | cut -d' ' -f1)
|
||||
caa_record=$($BIN/v-list-dns-records "$user" "$domain" | grep -i "letsencrypt" | cut -d' ' -f1)
|
||||
|
||||
if [ "$dns_domain" = "$domain" ]; then
|
||||
if [ -n "$caa_record" ]; then
|
||||
$BIN/v-delete-dns-record "$user" "$domain" "$caa_record"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
check_result "$E_CONNECT" "Let's Encrypt domain verification failed ($domain)"
|
||||
fi
|
||||
done
|
||||
|
||||
# Generating new ssl certificate
|
||||
ssl_dir=$($BIN/v-generate-ssl-cert "$domain" "info@$domain" "US" "California" \
|
||||
"San Francisco" "Hestia" "IT" "$aliases" | tail -n1 | awk '{print $2}')
|
||||
|
||||
# Sending CSR to finalize order / STEP 6
|
||||
csr=$(openssl req -in $ssl_dir/$domain.csr -outform DER | encode_base64)
|
||||
payload='{"csr":"'$csr'"}'
|
||||
answer=$(query_le_v2 "$finalize" "$payload" "$nonce")
|
||||
nonce=$(echo "$answer" | grep -i nonce | cut -f2 -d \ | tr -d '\r\n')
|
||||
status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f 2 -d ' ')
|
||||
certificate=$(echo "$answer" | grep 'certificate":' | cut -f4 -d '"')
|
||||
|
||||
debug_log "Step 6" "- status: ${status}\n- nonce: ${nonce}\n- payload: ${payload}\n- certificate: ${certificate}\n- answer: ${answer}"
|
||||
|
||||
if [[ "$status" -ne 200 ]]; then
|
||||
[ -d "$ssl_dir" ] && rm -rf "$ssl_dir"
|
||||
check_result "$E_CONNECT" "Let's Encrypt finalize bad status $status ($domain)"
|
||||
fi
|
||||
|
||||
if [ -z "$certificate" ]; then
|
||||
validation="processing"
|
||||
i=1
|
||||
while [ "$validation" = "processing" ]; do
|
||||
answer=$(query_le_v2 "$order" "" "$nonce")
|
||||
i=$((i + 1))
|
||||
|
||||
nonce=$(echo "$answer" | grep -i nonce | cut -f2 -d \ | tr -d '\r\n')
|
||||
status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f 2 -d ' ')
|
||||
validation=$(echo "$answer" | grep 'status":' | cut -f4 -d '"')
|
||||
certificate=$(echo "$answer" | grep 'certificate":' | cut -f4 -d '"')
|
||||
sleep $((i * 2)) # Sleep for 2s, 4s, 6s, 8s
|
||||
if [ $i -gt 10 ]; then
|
||||
check_result "$E_CONNECT" "Certificate processing timeout ($domain)"
|
||||
fi
|
||||
debug_log "Step 7" "- status: ${status}\n- nonce: ${nonce}\n- payload: ${payload}\n- certificate: ${certificate}\n- answer: ${answer}"
|
||||
done
|
||||
fi
|
||||
|
||||
# Downloading signed certificate / STEP 7
|
||||
status=0
|
||||
retry=0
|
||||
|
||||
while [[ $status != 200 && $retry -lt 3 ]]; do
|
||||
|
||||
answer=$(query_le_v2 "$certificate" "" "$nonce" "$ssl_dir/$domain.pem")
|
||||
status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f 2 -d ' ')
|
||||
|
||||
debug_log "Step 8" "- status: ${status}\n- retry: ${retry}\n- answer: ${answer}"
|
||||
|
||||
if [[ $status != 200 ]]; then
|
||||
retry=$((retry + 1))
|
||||
sleep $((retry * 2)) # Sleep for 2s, 4s, 6s, 8s
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
# Fallback on depreciated download method for certs (unauthenticated GET)
|
||||
if [[ $status != 200 ]]; then
|
||||
answer=$(curl --insecure --user-agent "HestiaCP" --retry 5 --retry-connrefused --silent --dump-header /dev/stdout "$certificate" --output "$ssl_dir/$domain.pem")
|
||||
status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f 2 -d ' ')
|
||||
|
||||
debug_log "Step 8 - Fallback" "- status: ${status}\n- answer: ${answer}"
|
||||
fi
|
||||
|
||||
debug_log "CERT DIR" "$(ls -las "$ssl_dir/")"
|
||||
debug_log "CERT PEM" "$(cat "$ssl_dir/$domain.pem")"
|
||||
|
||||
if [[ "$status" -ne 200 ]]; then
|
||||
[ -d "$ssl_dir" ] && rm -rf "$ssl_dir"
|
||||
check_result "$E_NOTEXIST" "Let's Encrypt downloading signed cert failed status:$status ($domain)"
|
||||
fi
|
||||
|
||||
# Splitting up downloaded pem
|
||||
crt_end=$(grep -n 'END CERTIFICATE' $ssl_dir/$domain.pem | head -n1 | cut -f1 -d:)
|
||||
head -n $crt_end $ssl_dir/$domain.pem > $ssl_dir/$domain.crt
|
||||
|
||||
pem_lines=$(wc -l $ssl_dir/$domain.pem | cut -f 1 -d ' ')
|
||||
ca_end=$(grep -n 'BEGIN CERTIFICATE' $ssl_dir/$domain.pem | tail -n1 | cut -f 1 -d :)
|
||||
ca_end=$((pem_lines - crt_end + 1))
|
||||
tail -n $ca_end $ssl_dir/$domain.pem > $ssl_dir/$domain.ca
|
||||
|
||||
debug_log "CERT CRT" "$(cat "$ssl_dir/$domain.crt")"
|
||||
debug_log "CERT CA-1" "$(cat "$ssl_dir/$domain.ca")"
|
||||
# Temporary fix for double "END CERTIFICATE"
|
||||
if [[ $(head -n 1 $ssl_dir/$domain.ca) = "-----END CERTIFICATE-----" ]]; then
|
||||
sed -i '1,2d' $ssl_dir/$domain.ca
|
||||
fi
|
||||
debug_log "CERT CA-2" "$(cat "$ssl_dir/$domain.ca")"
|
||||
|
||||
# Rename certs for mail
|
||||
if [ -n "$mail" ]; then
|
||||
mv $ssl_dir/$domain.ca $ssl_dir/$root_domain.ca
|
||||
mv $ssl_dir/$domain.crt $ssl_dir/$root_domain.crt
|
||||
mv $ssl_dir/$domain.csr $ssl_dir/$root_domain.csr
|
||||
mv $ssl_dir/$domain.key $ssl_dir/$root_domain.key
|
||||
mv $ssl_dir/$domain.pem $ssl_dir/$root_domain.pem
|
||||
fi
|
||||
|
||||
# Adding SSL
|
||||
if [ -z "$mail" ]; then
|
||||
ssl_home="$(get_object_value 'web' 'DOMAIN' "$domain" '$SSL_HOME')"
|
||||
ssl_enabled="$(get_object_value 'web' 'DOMAIN' "$domain" '$SSL')"
|
||||
if [ "$ssl_enabled" = "yes" ]; then
|
||||
$BIN/v-update-web-domain-ssl "$user" "$domain" "$ssl_dir" "updatessl"
|
||||
else
|
||||
$BIN/v-add-web-domain-ssl "$user" "$domain" "$ssl_dir" "$ssl_home" "updatessl"
|
||||
fi
|
||||
else
|
||||
# TODO replace with v-update-mail-domain-ssl if ssl is enabled
|
||||
ssl_enabled="$(get_object_value 'mail' 'DOMAIN' "$root_domain" '$SSL')"
|
||||
if [ "$ssl_enabled" = "yes" ]; then
|
||||
$BIN/v-update-mail-domain-ssl "$user" "$root_domain" "$ssl_dir" "updatessl"
|
||||
else
|
||||
$BIN/v-add-mail-domain-ssl "$user" "$root_domain" "$ssl_dir" "updatessl"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$?" -ne '0' ]; then
|
||||
[ -d "$ssl_dir" ] && rm -rf "$ssl_dir"
|
||||
touch $HESTIA/data/queue/letsencrypt.pipe
|
||||
sed -i "/ $domain /d" $HESTIA/data/queue/letsencrypt.pipe
|
||||
send_notice 'LETSENCRYPT' "$domain certificate installation failed ($domain)"
|
||||
check_result $? "SSL install" > /dev/null
|
||||
fi
|
||||
|
||||
# Adding LE autorenew cronjob
|
||||
if [ -z "$(grep v-update-lets $HESTIA/data/users/admin/cron.conf)" ]; then
|
||||
min=$(generate_password '012345' '2')
|
||||
hour=$(generate_password '1234567' '1')
|
||||
cmd="sudo $BIN/v-update-letsencrypt-ssl"
|
||||
$BIN/v-add-cron-job admin "$min" "$hour" '*' '*' '*' "$cmd" > /dev/null
|
||||
fi
|
||||
|
||||
# Updating letsencrypt key
|
||||
if [ -z "$mail" ]; then
|
||||
if [ -z "$LETSENCRYPT" ]; then
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'LETSENCRYPT' 'FTP_USER'
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'LETSENCRYPT_FAIL_COUNT' 'LETSENCRYPT'
|
||||
fi
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$LETSENCRYPT' 'yes'
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$LETSENCRYPT_FAIL_COUNT' "0"
|
||||
|
||||
if [[ "$domain_forcessl" == 'yes' ]]; then
|
||||
$BIN/v-add-web-domain-ssl-force $user $domain
|
||||
fi
|
||||
if [[ -n "$domain_redirect" ]]; then
|
||||
$BIN/v-add-web-domain-redirect $user $domain $domain_redirect $domain_redirect_code
|
||||
fi
|
||||
|
||||
else
|
||||
if [ -z "$LETSENCRYPT" ]; then
|
||||
add_object_key "mail" 'DOMAIN' "$root_domain" 'LETSENCRYPT'
|
||||
add_object_key "mail" 'DOMAIN' "$root_domain" 'LETSENCRYPT_FAIL_COUNT' 'LETSENCRYPT'
|
||||
fi
|
||||
update_object_value 'mail' 'DOMAIN' "$root_domain" '$LETSENCRYPT' 'yes'
|
||||
update_object_value 'mail' 'DOMAIN' "$root_domain" '$LETSENCRYPT_FAIL_COUNT' "0"
|
||||
fi
|
||||
|
||||
# Remove challenge folder if exist
|
||||
if [ -n "$well_known" ]; then
|
||||
rm -fr $well_known
|
||||
fi
|
||||
|
||||
# Remove temporary SSL folder
|
||||
[ -d "$ssl_dir" ] && rm -rf "$ssl_dir"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Deleting task from queue
|
||||
touch $HESTIA/data/queue/letsencrypt.pipe
|
||||
sed -i "/ $domain /d" $HESTIA/data/queue/letsencrypt.pipe
|
||||
|
||||
# Notifying user
|
||||
send_notice 'LETSENCRYPT' "$domain SSL has been installed successfully"
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
# Cleanup debug since the SSL was issues successfully
|
||||
rm -f "$log_file"
|
||||
|
||||
exit
|
@ -0,0 +1,98 @@
|
||||
#!/bin/bash
|
||||
# info: add letsencrypt for host and backend
|
||||
# options: NONE
|
||||
#
|
||||
# example: v-add-letsencrypt-host
|
||||
#
|
||||
# This function check and validates the backend certificate and generate
|
||||
# a new let's encrypt certificate.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
# Argument definition
|
||||
domain=$(hostname -f)
|
||||
if [ -z $domain ]; then
|
||||
domain=$HOSTNAME
|
||||
fi
|
||||
user="$($BIN/v-search-domain-owner "$domain" web)"
|
||||
[[ -z "$user" ]] && user="admin"
|
||||
|
||||
USER_DATA=$HESTIA/data/users/$user
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
is_format_valid 'user' 'domain' 'aliases'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Check if hostname already exists as domain
|
||||
if [ "$($BIN/v-list-web-domain $user $domain plain | cut -f 1)" != "$domain" ]; then
|
||||
# Create web domain for hostname
|
||||
$BIN/v-add-web-domain "$user" "$domain"
|
||||
fi
|
||||
|
||||
# Validate web domain
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
get_domain_values 'web'
|
||||
|
||||
# Load domain data
|
||||
parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf)
|
||||
|
||||
# Set ssl installation to yes
|
||||
add_ssl="yes"
|
||||
|
||||
if [ "$SSL" = "yes" ]; then
|
||||
# Valildate SSL Certificate
|
||||
if [ -e "$USER_DATA/ssl/$domain.ca" ]; then
|
||||
if openssl verify -CAfile <(openssl x509 -in $USER_DATA/ssl/$domain.ca) $USER_DATA/ssl/$domain.pem | grep -q "$domain.pem: OK"; then
|
||||
add_ssl="no"
|
||||
fi
|
||||
else
|
||||
if openssl verify $USER_DATA/ssl/$domain.pem | grep -q "$domain.pem: OK"; then
|
||||
add_ssl="no"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Add let's encrypt ssl if needed
|
||||
if [ "$add_ssl" = "yes" ]; then
|
||||
# Add let's encrypt ssl
|
||||
$BIN/v-add-letsencrypt-domain "$user" "$domain"
|
||||
check_result $? "Let's Encrypt SSL creation failed" "$E_UPDATE"
|
||||
fi
|
||||
|
||||
# Add certificate to backend
|
||||
$BIN/v-update-host-certificate "$user" "$domain"
|
||||
|
||||
# Enable automatic ssl forward and hsts
|
||||
$BIN/v-add-web-domain-ssl-force "$user" "$domain" > /dev/null 2>&1
|
||||
$BIN/v-add-web-domain-ssl-hsts "$user" "$domain" > /dev/null 2>&1
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
exit
|
@ -0,0 +1,148 @@
|
||||
#!/bin/bash
|
||||
# info: register letsencrypt user account
|
||||
# options: USER
|
||||
#
|
||||
# example: v-add-letsencrypt-user bob
|
||||
#
|
||||
# This function creates and register LetsEncrypt account
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# LE API
|
||||
LE_API='https://acme-v02.api.letsencrypt.org'
|
||||
|
||||
if [[ "$LE_STAGING" = 'yes' ]]; then
|
||||
LE_API='https://acme-staging-v02.api.letsencrypt.org'
|
||||
fi
|
||||
|
||||
# encode base64
|
||||
encode_base64() {
|
||||
cat | base64 | tr '+/' '-_' | tr -d '\r\n='
|
||||
}
|
||||
|
||||
# Let's Encrypt v2 curl function
|
||||
query_le_v2() {
|
||||
protected='{"nonce": "'$3'",'
|
||||
protected=''$protected' "url": "'$1'",'
|
||||
protected=''$protected' "alg": "RS256", "jwk": '$jwk'}'
|
||||
content="Content-Type: application/jose+json"
|
||||
|
||||
payload_=$(echo -n "$2" | encode_base64)
|
||||
protected_=$(echo -n "$protected" | encode_base64)
|
||||
signature_=$(printf "%s" "$protected_.$payload_" \
|
||||
| openssl dgst -sha256 -binary -sign $USER_DATA/ssl/user.key \
|
||||
| encode_base64)
|
||||
|
||||
post_data='{"protected":"'"$protected_"'",'
|
||||
post_data=$post_data'"payload":"'"$payload_"'",'
|
||||
post_data=$post_data'"signature":"'"$signature_"'"}'
|
||||
|
||||
curl --user-agent "HestiaCP" -s -i -d "$post_data" "$1" -H "$content"
|
||||
}
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'USER'
|
||||
is_format_valid 'user'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
if [ -e "$USER_DATA/ssl/le.conf" ]; then
|
||||
source "$USER_DATA/ssl/le.conf"
|
||||
fi
|
||||
if [ -n "$KID" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Defining user email
|
||||
if [[ -z "$EMAIL" ]]; then
|
||||
EMAIL=$(get_user_value '$CONTACT')
|
||||
fi
|
||||
|
||||
# Defining user agreement
|
||||
agreement=''
|
||||
|
||||
# Generating user key
|
||||
KEY="$USER_DATA/ssl/user.key"
|
||||
if [ ! -e "$KEY" ]; then
|
||||
openssl genrsa -out "$KEY" 4096 > /dev/null 2>&1
|
||||
chmod 600 $KEY
|
||||
fi
|
||||
|
||||
# Defining key exponent
|
||||
if [ -z "$EXPONENT" ]; then
|
||||
EXPONENT=$(openssl pkey -inform pem -in "$KEY" -noout -text_pub \
|
||||
| grep Exponent: | cut -f 2 -d '(' | cut -f 1 -d ')' | sed -e 's/x//' \
|
||||
| xxd -r -p | encode_base64)
|
||||
fi
|
||||
|
||||
# Defining key modulus
|
||||
if [ -z "$MODULUS" ]; then
|
||||
MODULUS=$(openssl rsa -in "$KEY" -modulus -noout \
|
||||
| sed -e 's/^Modulus=//' | xxd -r -p | encode_base64)
|
||||
fi
|
||||
|
||||
# Defining JWK
|
||||
jwk='{"e":"'$EXPONENT'","kty":"RSA","n":"'"$MODULUS"'"}'
|
||||
|
||||
# Defining key thumbnail
|
||||
if [ -z "$THUMB" ]; then
|
||||
THUMB="$(echo -n "$jwk" | openssl dgst -sha256 -binary | encode_base64)"
|
||||
fi
|
||||
|
||||
# Requesting ACME nonce
|
||||
nonce=$(curl -s -I "$LE_API/directory" | grep -i nonce | cut -f2 -d\ | tr -d '\r\n')
|
||||
|
||||
# Creating ACME account
|
||||
url="$LE_API/acme/new-acct"
|
||||
payload='{"termsOfServiceAgreed": true}'
|
||||
answer=$(query_le_v2 "$url" "$payload" "$nonce")
|
||||
kid=$(echo "$answer" | grep -i location: | cut -f2 -d ' ' | tr -d '\r')
|
||||
|
||||
# Checking answer status
|
||||
status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f2 -d ' ')
|
||||
if [[ "${status:0:2}" -ne "20" ]]; then
|
||||
check_result "$E_CONNECT" "Let's Encrypt acc registration failed $status"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding le.conf
|
||||
if [ ! -e "$USER_DATA/ssl/le.conf" ]; then
|
||||
echo "EXPONENT='$EXPONENT'" > $USER_DATA/ssl/le.conf
|
||||
echo "MODULUS='$MODULUS'" >> $USER_DATA/ssl/le.conf
|
||||
echo "THUMB='$THUMB'" >> $USER_DATA/ssl/le.conf
|
||||
echo "EMAIL='$EMAIL'" >> $USER_DATA/ssl/le.conf
|
||||
echo "KID='$kid'" >> $USER_DATA/ssl/le.conf
|
||||
chmod 660 $USER_DATA/ssl/le.conf
|
||||
else
|
||||
sed -i '/^KID=/d' $USER_DATA/ssl/le.conf
|
||||
echo "KID='$kid'" >> $USER_DATA/ssl/le.conf
|
||||
fi
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,139 @@
|
||||
#!/bin/bash
|
||||
# info: add mail domain account
|
||||
# options: USER DOMAIN ACCOUNT PASSWORD [QUOTA]
|
||||
#
|
||||
# example: v-add-mail-account user example.com john P4$$vvOrD
|
||||
#
|
||||
# This function add new email account.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
account=$3
|
||||
password=$4
|
||||
HIDE=4
|
||||
quota=${5-unlimited}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/syshealth.sh
|
||||
source $HESTIA/func/syshealth.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
if [[ "$account" =~ [[:upper:]] ]]; then
|
||||
account=$(echo "$account" | tr '[:upper:]' '[:lower:]')
|
||||
fi
|
||||
|
||||
format_domain
|
||||
format_domain_idn
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '4' "$#" 'USER DOMAIN ACCOUNT PASSWORD [QUOTA]'
|
||||
is_format_valid 'user' 'domain' 'account'
|
||||
if [ "$quota" != 'unlimited' ]; then
|
||||
is_format_valid 'quota'
|
||||
fi
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_package_full 'MAIL_ACCOUNTS'
|
||||
is_mail_new "$account"
|
||||
is_password_valid
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating hashed password
|
||||
|
||||
if [ -n "$(doveadm pw -l | grep BLF-CRYPT)" ]; then
|
||||
set +H # disable ! style history substitution
|
||||
md5="$(doveadm pw -s BLF-CRYPT -p "$password")"
|
||||
elif [ -n "$(doveadm pw -l | grep ARGON2ID)" ]; then
|
||||
# Fall back on Argon2id if bcrypt is not available
|
||||
set +H # disable ! style history substitution
|
||||
md5="$(doveadm pw -s ARGON2ID -p "$password")"
|
||||
else
|
||||
# Fall back on MD5 if neither bcrypt nor argon2id is available
|
||||
salt=$(generate_password "$PW_MATRIX" "8")
|
||||
md5="{MD5}$($BIN/v-generate-password-hash md5 $salt <<< $password)"
|
||||
fi
|
||||
# Adding account info into password file
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
if [ "$quota" = 'unlimited' ]; then
|
||||
quota='0'
|
||||
fi
|
||||
str="$account:$md5:$user:mail::$HOMEDIR/$user:${quota}:userdb_quota_rule=*:storage=${quota}M"
|
||||
echo $str >> $HOMEDIR/$user/conf/mail/$domain/passwd
|
||||
userstr="$account:$account:$user:mail:$HOMEDIR/$user"
|
||||
echo $userstr >> $HOMEDIR/$user/conf/mail/$domain/accounts
|
||||
fi
|
||||
|
||||
# Create mail account folder (mailbox)
|
||||
mkdir $HOMEDIR/$user/mail/$domain_idn/$account
|
||||
chown $user:mail $HOMEDIR/$user/mail/$domain_idn/$account
|
||||
chmod 700 $HOMEDIR/$user/mail/$domain_idn/$account
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
if [[ "$quota" -eq '0' ]]; then
|
||||
quota='unlimited'
|
||||
fi
|
||||
|
||||
str="ACCOUNT='$account' ALIAS='' AUTOREPLY='no' FWD='' FWD_ONLY=''"
|
||||
str="$str MD5='$md5' QUOTA='$quota' U_DISK='0' SUSPENDED='no'"
|
||||
str="$str TIME='$time' DATE='$date'"
|
||||
echo "$str" >> $USER_DATA/mail/$domain.conf
|
||||
chmod 660 $USER_DATA/mail/$domain.conf
|
||||
|
||||
syshealth_repair_mail_account_config
|
||||
|
||||
touch $HOMEDIR/$user/conf/mail/$domain/limits
|
||||
|
||||
user_rate_limit=$(get_object_value 'mail' 'DOMAIN' "$domain" '$RATE_LIMIT')
|
||||
if [ -n "$user_rate_limit" ]; then
|
||||
sed -i "/^$account@$domain_idn:/ d" $HOMEDIR/$user/conf/mail/$domain/limits
|
||||
echo "$account@$domain_idn:$user_rate_limit" >> $HOMEDIR/$user/conf/mail/$domain/limits
|
||||
else
|
||||
system=$(cat /etc/exim4/limit.conf)
|
||||
sed -i "/^$account@$domain_idn:/ d" $HOMEDIR/$user/conf/mail/$domain/limits
|
||||
echo "$account@$domain_idn:$system" >> $HOMEDIR/$user/conf/mail/$domain/limits
|
||||
fi
|
||||
|
||||
# Increase mail accounts counter
|
||||
accounts=$(wc -l $USER_DATA/mail/$domain.conf | cut -f 1 -d ' ')
|
||||
increase_user_value "$user" '$U_MAIL_ACCOUNTS'
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$ACCOUNTS' "$accounts"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "Added new mail account ($account@$domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,80 @@
|
||||
#!/bin/bash
|
||||
# info: add mail account alias aka nickname
|
||||
# options: USER DOMAIN ACCOUNT ALIAS
|
||||
#
|
||||
# example: v-add-mail-account-alias admin acme.com alice alicia
|
||||
#
|
||||
# This function add new email alias.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
account=$3
|
||||
malias=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '4' "$#" 'USER DOMAIN ACCOUNT ALIAS'
|
||||
is_format_valid 'user' 'domain' 'account' 'malias'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_object_valid "mail/$domain" 'ACCOUNT' "$account"
|
||||
is_object_unsuspended "mail/$domain" 'ACCOUNT' "$account"
|
||||
is_mail_new "$malias"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding exim alias
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
str="$malias@$domain_idn:$account@$domain_idn"
|
||||
echo "$str" >> $HOMEDIR/$user/conf/mail/$domain/aliases
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding hestia alias
|
||||
aliases=$(get_object_value "mail/$domain" 'ACCOUNT' "$account" '$ALIAS')
|
||||
if [ -z "$aliases" ]; then
|
||||
aliases="$malias"
|
||||
else
|
||||
aliases="$aliases,$malias"
|
||||
fi
|
||||
update_object_value "mail/$domain" 'ACCOUNT' "$account" '$ALIAS' "$aliases"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "Added alias $malias to mail account $account@$domain."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,85 @@
|
||||
#!/bin/bash
|
||||
# info: add mail account autoreply message
|
||||
# options: USER DOMAIN ACCOUNT MESSAGE
|
||||
#
|
||||
# example: v-add-mail-account-autoreply admin example.com user Hello from e-mail!
|
||||
#
|
||||
# This function add new email account.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
account=$3
|
||||
autoreply=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Define mail user
|
||||
if [ "$MAIL_SYSTEM" = 'exim4' ]; then
|
||||
MAIL_USER=Debian-exim
|
||||
else
|
||||
MAIL_USER=exim
|
||||
fi
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '4' "$#" 'USER DOMAIN ACCOUNT MESSAGE'
|
||||
is_format_valid 'user' 'domain' 'account' 'autoreply'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_object_valid "mail/$domain" 'ACCOUNT' "$account"
|
||||
is_object_unsuspended "mail/$domain" 'ACCOUNT' "$account"
|
||||
# is_object_value_empty "mail/$domain" 'ACCOUNT' "$account" '$AUTOREPLY'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding exim autoreply
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
msg="$HOMEDIR/$user/conf/mail/$domain/autoreply.$account.msg"
|
||||
echo -e "$autoreply" > $msg
|
||||
chown $MAIL_USER:mail $msg
|
||||
chmod 660 $msg
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding autoreply message
|
||||
echo -e "$autoreply" > $USER_DATA/mail/$account@$domain.msg
|
||||
chmod 660 $USER_DATA/mail/$account@$domain.msg
|
||||
update_object_value "mail/$domain" 'ACCOUNT' "$account" '$AUTOREPLY' 'yes'
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "Added auto-reply message for mail account $account@$domain."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,88 @@
|
||||
#!/bin/bash
|
||||
# info: add mail account forward address
|
||||
# options: USER DOMAIN ACCOUNT FORWARD
|
||||
#
|
||||
# example: v-add-mail-account-forward admin acme.com alice bob
|
||||
#
|
||||
# This function add new email account.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
account=$3
|
||||
email_forward=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '4' "$#" 'USER DOMAIN ACCOUNT FORWARD'
|
||||
is_format_valid 'user' 'domain' 'account'
|
||||
if [ "$email_forward" != ':blackhole:' ]; then
|
||||
is_format_valid 'email_forward'
|
||||
fi
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_object_valid "mail/$domain" 'ACCOUNT' "$account"
|
||||
is_object_unsuspended "mail/$domain" 'ACCOUNT' "$account"
|
||||
fwd=$(get_object_value "mail/$domain" 'ACCOUNT' "$account" '$FWD')
|
||||
if [ -n "$(echo $fwd | grep -w "$email_forward")" ]; then
|
||||
echo "Error: forward $email_forward exists"
|
||||
log_event "$E_EXISTS" "$ARGUMENTS"
|
||||
exit $E_EXISTS
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Define fwd string
|
||||
if [ -z "$fwd" ]; then
|
||||
fwd="$email_forward"
|
||||
else
|
||||
fwd="$fwd,$email_forward"
|
||||
fi
|
||||
|
||||
# Adding forward to exim
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
sed -i "/^$account@$domain_idn:/ d" $HOMEDIR/$user/conf/mail/$domain/aliases
|
||||
echo "$account@$domain_idn:$fwd" >> $HOMEDIR/$user/conf/mail/$domain/aliases
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Updating config
|
||||
update_object_value "mail/$domain" 'ACCOUNT' "$account" '$FWD' "$fwd"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Warning" "Mail" "Mail forwarding on mail account $account@$domain enabled (send to: $email_forward)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,86 @@
|
||||
#!/bin/bash
|
||||
# info: add mail account forward-only flag
|
||||
# options: USER DOMAIN ACCOUNT
|
||||
#
|
||||
# example: v-add-mail-account-fwd-only admin example.com user
|
||||
#
|
||||
# This function adds fwd-only flag
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
account=$3
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Define mail user
|
||||
if [ "$MAIL_SYSTEM" = 'exim4' ]; then
|
||||
MAIL_USER=Debian-exim
|
||||
else
|
||||
MAIL_USER=exim
|
||||
fi
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN ACCOUNT'
|
||||
is_format_valid 'user' 'domain' 'account'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_object_valid "mail/$domain" 'ACCOUNT' "$account"
|
||||
is_object_unsuspended "mail/$domain" 'ACCOUNT' "$account"
|
||||
fwd=$(get_object_value "mail/$domain" 'ACCOUNT' "$account" '$FWD')
|
||||
if [ -z "$fwd" ]; then
|
||||
echo "Error: forward doesn't exist"
|
||||
log_event "$E_NOTEXIST" "$ARGUMENTS"
|
||||
exit "$E_NOTEXIST"
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding account to fwd_only
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
echo "$account" >> $HOMEDIR/$user/conf/mail/$domain/fwd_only
|
||||
chown -R $MAIL_USER:mail $HOMEDIR/$user/conf/mail/$domain/fwd_only
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Updating config
|
||||
add_object_key "mail/$domain" 'ACCOUNT' "$account" 'FWD_ONLY' 'MD5'
|
||||
update_object_value "mail/$domain" 'ACCOUNT' "$account" '$FWD_ONLY' "yes"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Warning" "Mail" "Forward-only flag enabled on mail account $account@$domain."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,224 @@
|
||||
#!/bin/bash
|
||||
# info: add mail domain
|
||||
# options: USER DOMAIN [ANTISPAM] [ANTIVIRUS] [DKIM] [DKIM_SIZE] [RESTART] [REJECT_SPAM]
|
||||
#
|
||||
# example: v-add-mail-domain admin mydomain.tld
|
||||
#
|
||||
# This function adds MAIL domain.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
antispam=${3-yes}
|
||||
antivirus=${4-yes}
|
||||
dkim=${5-yes}
|
||||
dkim_size=${6-1024}
|
||||
restart="$7"
|
||||
reject=${8-no}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# shellcheck source=/usr/local/hestia/func/syshealth.sh
|
||||
source $HESTIA/func/syshealth.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Define mail user
|
||||
if [ "$MAIL_SYSTEM" = 'exim4' ]; then
|
||||
MAIL_USER=Debian-exim
|
||||
else
|
||||
MAIL_USER=exim
|
||||
fi
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
domain_utf=$(idn2 --quiet -d "$domain_idn")
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN [ANTISPAM] [ANTIVIRUS] [DKIM] [DKIM_SIZE] [RESTART] [REJECT_SPAM]'
|
||||
is_format_valid 'user' 'domain' 'antispam' 'antivirus' 'dkim' 'dkim_size' 'restart' 'reject'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
|
||||
if [ "$($BIN/v-list-mail-domain $user $domain_utf plain | cut -f 1) " != "$domain" ]; then
|
||||
is_domain_new 'mail' "$domain_utf"
|
||||
fi
|
||||
if [ "$($BIN/v-list-mail-domain $user $domain_idn plain | cut -f 1) " != "$domain" ]; then
|
||||
is_domain_new 'mail' "$domain_idn"
|
||||
else
|
||||
is_domain_new 'mail' "$domain"
|
||||
fi
|
||||
if [ -z "$(is_ip_format_valid $domain)" ]; then
|
||||
echo "Error: Invalid domain format. IP address detected as input."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
is_package_full 'MAIL_DOMAINS'
|
||||
is_dir_symlink $HOMEDIR/$user/mail
|
||||
|
||||
is_base_domain_owner "$domain"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
source_conf "$USER_DATA/user.conf"
|
||||
# Inherit web domain local ip address
|
||||
domain_ip=$(get_object_value 'web' 'DOMAIN' "$domain" '$IP')
|
||||
if [ ! -z "$domain_ip" ]; then
|
||||
local_ip=$(get_real_ip "$domain_ip")
|
||||
is_ip_valid "$local_ip" "$user"
|
||||
else
|
||||
get_user_ip
|
||||
fi
|
||||
|
||||
# Generating timestamp
|
||||
new_timestamp
|
||||
|
||||
if [ -z "$ANTISPAM_SYSTEM" ]; then
|
||||
antispam="no"
|
||||
reject="no"
|
||||
fi
|
||||
if [ -z "$ANTIVIRUS_SYSTEM" ]; then
|
||||
antivirus="no"
|
||||
fi
|
||||
|
||||
# Adding domain to mail.conf
|
||||
s="DOMAIN='$domain' ANTIVIRUS='$antivirus' ANTISPAM='$antispam' REJECT='$reject' DKIM='$dkim' WEBMAIL=''"
|
||||
s="$s SSL='no' LETSENCRYPT='no' CATCHALL='' ACCOUNTS='0' RATE_LIMIT='$RATE_LIMIT' U_DISK='0' SUSPENDED='no' TIME='$time'"
|
||||
s="$s DATE='$date'"
|
||||
echo $s >> $USER_DATA/mail.conf
|
||||
touch $USER_DATA/mail/$domain.conf
|
||||
|
||||
syshealth_repair_mail_config
|
||||
|
||||
# Generating DKIM keys
|
||||
if [ "$dkim" = 'yes' ]; then
|
||||
openssl genrsa -out $USER_DATA/mail/$domain.pem $dkim_size &> /dev/null
|
||||
openssl rsa -pubout -in $USER_DATA/mail/$domain.pem \
|
||||
-out $USER_DATA/mail/$domain.pub &> /dev/null
|
||||
fi
|
||||
|
||||
# Set permissions
|
||||
chmod 660 $USER_DATA/mail/$domain.*
|
||||
chmod 660 $USER_DATA/mail.conf
|
||||
|
||||
# Building exim configs
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
mkdir $HOMEDIR/$user/conf/mail/$domain
|
||||
mkdir $HOMEDIR/$user/mail/$domain_idn
|
||||
touch $HOMEDIR/$user/conf/mail/$domain/aliases
|
||||
touch $HOMEDIR/$user/conf/mail/$domain/passwd
|
||||
touch $HOMEDIR/$user/conf/mail/$domain/fwd_only
|
||||
touch $HOMEDIR/$user/conf/mail/$domain/accounts
|
||||
ln -s $HOMEDIR/$user/conf/mail/$domain \
|
||||
/etc/$MAIL_SYSTEM/domains/$domain_idn
|
||||
|
||||
# Seeting outgoing ip address
|
||||
if [ -n "$local_ip" ]; then
|
||||
echo "$local_ip" > $HOMEDIR/$user/conf/mail/$domain/ip
|
||||
fi
|
||||
|
||||
if [ -n "$ANTISPAM_SYSTEM" ]; then
|
||||
# Adding antispam protection
|
||||
if [ "$antispam" = 'yes' ]; then
|
||||
touch "$HOMEDIR/$user/conf/mail/$domain/antispam"
|
||||
fi
|
||||
if [ "$reject" = 'yes' ]; then
|
||||
touch "$HOMEDIR/$user/conf/mail/$domain/reject_spam"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$ANTIVIRUS_SYSTEM" ]; then
|
||||
# Adding antivirus protection
|
||||
if [ "$antivirus" = 'yes' ]; then
|
||||
touch "$HOMEDIR/$user/conf/mail/$domain/antivirus"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Adding dkim support
|
||||
if [ "$dkim" = 'yes' ]; then
|
||||
cp -f $USER_DATA/mail/$domain.pem \
|
||||
$HOMEDIR/$user/conf/mail/$domain/dkim.pem
|
||||
fi
|
||||
|
||||
# Set permission
|
||||
chmod 771 $HOMEDIR/$user/conf/mail/$domain
|
||||
chmod 660 $HOMEDIR/$user/conf/mail/$domain/*
|
||||
chmod 771 /etc/$MAIL_SYSTEM/domains/$domain_idn
|
||||
chmod 770 $HOMEDIR/$user/mail/$domain_idn
|
||||
|
||||
# Set ownership
|
||||
chown -R $MAIL_USER:mail $HOMEDIR/$user/conf/mail/$domain
|
||||
if [ "$IMAP_SYSTEM" = 'dovecot' ]; then
|
||||
chown -R dovecot:mail $HOMEDIR/$user/conf/mail/$domain/passwd
|
||||
fi
|
||||
chown $MAIL_USER:mail $HOMEDIR/$user/conf/mail/$domain/accounts
|
||||
chown $user:mail $HOMEDIR/$user/mail/$domain_idn
|
||||
fi
|
||||
|
||||
# Adding dkim dns records
|
||||
if [ -n "$DNS_SYSTEM" ] && [ "$dkim" = 'yes' ]; then
|
||||
check_dns_domain=$(is_object_valid 'dns' 'DOMAIN' "$domain")
|
||||
if [ "$?" -eq 0 ]; then
|
||||
p=$(cat $USER_DATA/mail/$domain.pub | grep -v ' KEY---' | tr -d '\n')
|
||||
record='_domainkey'
|
||||
policy="\"t=y; o=~;\""
|
||||
$BIN/v-add-dns-record "$user" "$domain" "$record" TXT "$policy" '' '' 'no' '' 'yes'
|
||||
|
||||
record='mail._domainkey'
|
||||
selector="\"v=DKIM1\; k=rsa\; p=$p\""
|
||||
$BIN/v-add-dns-record "$user" "$domain" "$record" TXT "$selector" '' '' 'yes' '' 'yes'
|
||||
fi
|
||||
fi
|
||||
|
||||
# Add webmail configuration to mail domain
|
||||
if [ -n "$WEB_SYSTEM" ] || [ -n "$PROXY_SYSTEM" ]; then
|
||||
if [ -n "$IMAP_SYSTEM" ]; then
|
||||
$BIN/v-add-mail-domain-webmail "$user" "$domain" '' 'no'
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Increasing domain value
|
||||
increase_user_value "$user" '$U_MAIL_DOMAINS'
|
||||
|
||||
if [ "$dkim" = 'yes' ]; then
|
||||
increase_user_value "$user" '$U_MAIL_DKIM'
|
||||
fi
|
||||
|
||||
# Restarting web server
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
|
||||
# Restarting proxy server
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "Added new mail domain ($domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,69 @@
|
||||
#!/bin/bash
|
||||
# info: add mail domain antispam support
|
||||
# options: USER DOMAIN
|
||||
#
|
||||
# example: v-add-mail-domain-antispam admin mydomain.tld
|
||||
#
|
||||
# This function enables spamassasin for incoming emails.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN'
|
||||
is_format_valid 'user' 'domain'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_object_value_empty 'mail' 'DOMAIN' "$domain" '$ANTISPAM'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding antispam flag
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
touch $HOMEDIR/$user/conf/mail/$domain/antispam
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding antispam in config
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$ANTISPAM' 'yes'
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "Anti-spam protection enabled (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,69 @@
|
||||
#!/bin/bash
|
||||
# info: add mail domain antivirus support
|
||||
# options: USER DOMAIN
|
||||
#
|
||||
# example: v-add-mail-domain-antivirus admin mydomain.tld
|
||||
#
|
||||
# This function enables clamav scan for incoming emails.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN'
|
||||
is_format_valid 'user' 'domain'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_object_value_empty 'mail' 'DOMAIN' "$domain" '$ANTIVIRUS'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding antivirus flag
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
touch $HOMEDIR/$user/conf/mail/$domain/antivirus
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding antivirus in config
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$ANTIVIRUS' 'yes'
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "Anti-virus scanning enabled (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,70 @@
|
||||
#!/bin/bash
|
||||
# info: add mail domain catchall account
|
||||
# options: USER DOMAIN EMAIL
|
||||
#
|
||||
# example: v-add-mail-domain-catchall admin example.com master@example.com
|
||||
#
|
||||
# This function enables catchall account for incoming emails.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
email="$3"
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN EMAIL'
|
||||
is_format_valid 'user' 'domain' 'email'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_object_value_empty 'mail' 'DOMAIN' "$domain" '$CATCHALL'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding catchall alias
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
sed -i "/*@$domain_idn:/d" $HOMEDIR/$user/conf/mail/$domain/aliases
|
||||
echo "*@$domain_idn:$email" >> $HOMEDIR/$user/conf/mail/$domain/aliases
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding antispam in config
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$CATCHALL' "$email"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Warning" "Mail" "Catch-all forwarding enabled (Domain: $domain, Send to: $email)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,98 @@
|
||||
#!/bin/bash
|
||||
# info: add mail domain dkim support
|
||||
# options: USER DOMAIN [DKIM_SIZE]
|
||||
#
|
||||
# example: v-add-mail-domain-dkim admin acme.com
|
||||
#
|
||||
# This function adds DKIM signature to outgoing domain emails.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
dkim_size=${3-2048}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Define mail user
|
||||
if [ "$MAIL_SYSTEM" = 'exim4' ]; then
|
||||
MAIL_USER=Debian-exim
|
||||
else
|
||||
MAIL_USER=exim
|
||||
fi
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN [DKIM_SIZE]'
|
||||
is_format_valid 'user' 'domain' 'dkim_size'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_object_value_empty 'mail' 'DOMAIN' "$domain" '$DKIM'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating dkim
|
||||
openssl genrsa -out $USER_DATA/mail/$domain.pem $dkim_size &> /dev/null
|
||||
openssl rsa -pubout -in $USER_DATA/mail/$domain.pem \
|
||||
-out $USER_DATA/mail/$domain.pub &> /dev/null
|
||||
chmod 660 $USER_DATA/mail/$domain.*
|
||||
|
||||
# Adding dkim keys
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
cp $USER_DATA/mail/$domain.pem $HOMEDIR/$user/conf/mail/$domain/dkim.pem
|
||||
chown $MAIL_USER:mail $HOMEDIR/$user/conf/mail/$domain/dkim.pem
|
||||
chmod 660 $HOMEDIR/$user/conf/mail/$domain/dkim.pem
|
||||
fi
|
||||
|
||||
# Adding dns records
|
||||
if [ -n "$DNS_SYSTEM" ] && [ -e "$USER_DATA/dns/$domain.conf" ]; then
|
||||
p=$(cat $USER_DATA/mail/$domain.pub | grep -v ' KEY---' | tr -d '\n')
|
||||
record="_domainkey"
|
||||
policy="\"t=y\; o=~\;\""
|
||||
$BIN/v-add-dns-record "$user" "$domain" "$record" TXT "$policy" '' '' 'no' '' 'yes'
|
||||
|
||||
record="mail._domainkey"
|
||||
selector="\"v=DKIM1\; k=rsa\; p=$p\""
|
||||
$BIN/v-add-dns-record "$user" "$domain" "$record" TXT "$selector" '' '' 'yes' '' 'yes'
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding dkim in config
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$DKIM' 'yes'
|
||||
increase_user_value "$user" '$U_MAIL_DKIM'
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "DKIM message signing enabled (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,71 @@
|
||||
#!/bin/bash
|
||||
# info: add mail domain reject spam support
|
||||
# options: USER DOMAIN
|
||||
# labels: mail
|
||||
#
|
||||
# example: v-add-mail-domain-reject admin mydomain.tld
|
||||
#
|
||||
# The function enables spam rejection for incoming emails.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variable&Function #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN'
|
||||
is_format_valid 'user' 'domain'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_object_value_empty 'mail' 'DOMAIN' "$domain" '$REJECT'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding antivirus flag
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
# Reject spam > 10 when enabled
|
||||
touch $HOMEDIR/$user/conf/mail/$domain/reject_spam
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding antivirus in config
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$REJECT' 'yes'
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "Anti-virus scanning enabled (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,81 @@
|
||||
#!/bin/bash
|
||||
# info: Add mail domain smtp relay support
|
||||
# options: USER DOMAIN HOST [USERNAME] [PASSWORD] [PORT]
|
||||
#
|
||||
# example: v-add-mail-domain-smtp-relay user domain.tld srv.smtprelay.tld uname123 pass12345
|
||||
#
|
||||
# This function adds mail domain smtp relay support.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
host=$3
|
||||
username=$4
|
||||
password=$5
|
||||
port=${6-587}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN HOST [USERNAME] [PASSWORD] [PORT]'
|
||||
is_format_valid 'port' 'user' 'domain' 'host'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_password_valid "$password" "Password"
|
||||
is_username_format_valid "$username" "Username"
|
||||
format_no_quotes "$password" "Password"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
cat > /etc/exim4/domains/${domain}/smtp_relay.conf << EOL
|
||||
host:$host
|
||||
port:$port
|
||||
user:$username
|
||||
pass:$password
|
||||
EOL
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding smtp relay values in config
|
||||
if [ -z "$U_SMTP_RELAY" ]; then
|
||||
add_object_key 'mail' 'DOMAIN' "$domain" 'U_SMTP_RELAY' 'ACCOUNTS'
|
||||
add_object_key 'mail' 'DOMAIN' "$domain" 'U_SMTP_RELAY_HOST' 'ACCOUNTS'
|
||||
add_object_key 'mail' 'DOMAIN' "$domain" 'U_SMTP_RELAY_PORT' 'ACCOUNTS'
|
||||
add_object_key 'mail' 'DOMAIN' "$domain" 'U_SMTP_RELAY_USERNAME' 'ACCOUNTS'
|
||||
add_object_key 'mail' 'DOMAIN' "$domain" 'U_SMTP_RELAY_PASSWORD' 'ACCOUNTS'
|
||||
fi
|
||||
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$U_SMTP_RELAY' 'true'
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$U_SMTP_RELAY_HOST' "$host"
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$U_SMTP_RELAY_PORT' "$port"
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$U_SMTP_RELAY_USERNAME' "$username"
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$U_SMTP_RELAY_PASSWORD' "$password"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "SMTP Relay enabled (Domain: $domain, Host: $host, Port: $port)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,144 @@
|
||||
#!/bin/bash
|
||||
# info: add mail SSL for $domain
|
||||
# options: USER DOMAIN SSL_DIR [RESTART]
|
||||
#
|
||||
# This function turns on SSL support for a mail domain. Parameter ssl_dir
|
||||
# is a path to a directory where 2 or 3 ssl files can be found. Certificate file
|
||||
# mail.domain.tld.crt and its key mail.domain.tld.key are mandatory. Certificate
|
||||
# authority mail.domain.tld.ca file is optional.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
ssl_dir=$3
|
||||
restart="$4"
|
||||
|
||||
# Additional argument formatting
|
||||
if [[ "$domain" =~ [[:upper:]] ]]; then
|
||||
domain=$(echo "$domain" | tr '[:upper:]' '[:lower:]')
|
||||
fi
|
||||
if [[ "$domain" =~ ^www\..* ]]; then
|
||||
domain=$(echo "$domain" | sed -e "s/^www.//")
|
||||
fi
|
||||
if [[ "$domain" =~ .*\.$ ]]; then
|
||||
domain=$(echo "$domain" | sed -e "s/\.$//")
|
||||
fi
|
||||
|
||||
domain_idn=$(idn2 --quiet "$domain")
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN SSL_DIR [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'ssl_dir'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_object_value_empty 'mail' 'DOMAIN' "$domain" '$SSL'
|
||||
is_web_domain_cert_valid
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
if [ -n "$restart" ]; then
|
||||
is_format_valid "$restart"
|
||||
fi
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Inherit web domain local ip address
|
||||
domain_ip=$(get_object_value 'web' 'DOMAIN' "$domain" '$IP')
|
||||
if [ -n "$domain_ip" ]; then
|
||||
local_ip=$(get_real_ip "$domain_ip")
|
||||
is_ip_valid "$local_ip" "$user"
|
||||
else
|
||||
get_user_ip
|
||||
fi
|
||||
|
||||
# Call routine to add SSL configuration to mail domain
|
||||
add_mail_ssl_config
|
||||
|
||||
if [ "$WEBMAIL" == "roundcube" ]; then
|
||||
WEBMAIL_TEMPLATE="default"
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
PROXY_TEMPLATE="default"
|
||||
fi
|
||||
# Add webmail configuration to mail domain
|
||||
WEBMAIL_TEMPLATE="default"
|
||||
if [ "$WEB_SYSTEM" = "nginx" ]; then
|
||||
WEBMAIL_TEMPLATE="web_system"
|
||||
fi
|
||||
elif [ "$WEBMAIL" == "snappymail" ]; then
|
||||
WEBMAIL_TEMPLATE="snappymail"
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
PROXY_TEMPLATE="default_snappymail"
|
||||
fi
|
||||
elif [ "$WEBMAIL" == "rainloop" ]; then
|
||||
WEBMAIL_TEMPLATE="rainloop"
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
PROXY_TEMPLATE="default_rainloop"
|
||||
fi
|
||||
else
|
||||
WEBMAIL_TEMPLATE="disabled"
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
PROXY_TEMPLATE="default_disabled"
|
||||
fi
|
||||
fi
|
||||
|
||||
add_webmail_config "$WEB_SYSTEM" "${WEBMAIL_TEMPLATE}.stpl"
|
||||
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
add_webmail_config "$PROXY_SYSTEM" "${PROXY_TEMPLATE}.stpl"
|
||||
fi
|
||||
|
||||
# Increase value for domain
|
||||
increase_user_value "$user" '$U_MAIL_SSL'
|
||||
|
||||
# Set SSL as enabled in configuration
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$SSL' "yes"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Restarting mail server
|
||||
$BIN/v-restart-mail "$restart"
|
||||
check_result $? "Mail restart failed" > /dev/null
|
||||
|
||||
# Restarting web server
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
|
||||
# Restarting proxy server
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "SSL enabled (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,190 @@
|
||||
#!/bin/bash
|
||||
# info: add webmail support for a domain
|
||||
# options: USER DOMAIN [WEBMAIL] [RESTART] [QUIET]
|
||||
#
|
||||
# example: v-add-sys-webmail user domain.com
|
||||
# example: v-add-sys-webmail user domain.com snappymail
|
||||
# example: v-add-sys-webmail user domain.com roundcube
|
||||
#
|
||||
# This function enables webmail client for a mail domain.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
webmail=$3
|
||||
restart="$4"
|
||||
quiet=$5
|
||||
|
||||
if [ -z "$restart" ]; then
|
||||
restart="yes"
|
||||
fi
|
||||
|
||||
# Additional argument formatting
|
||||
if [[ "$domain" =~ [[:upper:]] ]]; then
|
||||
domain=$(echo "$domain" | tr '[:upper:]' '[:lower:]')
|
||||
fi
|
||||
if [[ "$domain" =~ ^www\..* ]]; then
|
||||
domain=$(echo "$domain" | sed -e "s/^www.//")
|
||||
fi
|
||||
if [[ "$domain" =~ .*\.$ ]]; then
|
||||
domain=$(echo "$domain" | sed -e "s/\.$//")
|
||||
fi
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ -z "$webmail" ]; then
|
||||
for client in ${WEBMAIL_SYSTEM//,/ }; do
|
||||
webmail="$client"
|
||||
done
|
||||
fi
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN [WEBMAIL] [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'restart'
|
||||
is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
|
||||
is_system_enabled "$IMAP_SYSTEM" 'IMAP_SYSTEM'
|
||||
is_type_valid "$WEBMAIL_SYSTEM disabled" "$webmail"
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Inherit web domain local ip address
|
||||
domain_ip=$(get_object_value 'web' 'DOMAIN' "$domain" '$IP')
|
||||
if [ -n "$domain_ip" ]; then
|
||||
local_ip=$(get_real_ip "$domain_ip")
|
||||
is_ip_valid "$local_ip" "$user"
|
||||
|
||||
ip=$local_ip
|
||||
nat_ip=$(get_ip_value '$NAT')
|
||||
if [ -n "$nat_ip" ]; then
|
||||
ip=$nat_ip
|
||||
fi
|
||||
else
|
||||
get_user_ip
|
||||
fi
|
||||
|
||||
# Verify that webmail alias variable exists and create it if it does not
|
||||
if [ -z "$WEBMAIL_ALIAS" ]; then
|
||||
$BIN/v-change-sys-config-value 'WEBMAIL_ALIAS' "webmail"
|
||||
else
|
||||
# Ensure DNS record exists if Hestia is hosting DNS zones
|
||||
if [ -n "$DNS_SYSTEM" ]; then
|
||||
dns_domain=$($BIN/v-list-dns-domains $user | grep $domain | cut -d' ' -f1)
|
||||
webmail_record=$($BIN/v-list-dns-records $user $domain | grep -i " $WEBMAIL_ALIAS " | cut -d' ' -f1)
|
||||
if [ "$dns_domain" = "$domain" ]; then
|
||||
if [ "$WEBMAIL_ALIAS" != "mail" ]; then
|
||||
#Prevent mail.domain.com to be cycled
|
||||
if [ -z "$webmail_record" ]; then
|
||||
if [ "$quiet" = "yes" ]; then
|
||||
$BIN/v-add-dns-record "$user" "$domain" "$WEBMAIL_ALIAS" A "$ip" '' '' "$restart" '' 'yes'
|
||||
else
|
||||
$BIN/v-add-dns-record "$user" "$domain" "$WEBMAIL_ALIAS" A "$ip" '' '' "$restart" '' 'yes'
|
||||
fi
|
||||
else
|
||||
if [ "$quiet" = "yes" ]; then
|
||||
$BIN/v-delete-dns-record "$user" "$domain" "$webmail_record" "$restart" 'yes'
|
||||
$BIN/v-add-dns-record "$user" "$domain" "$WEBMAIL_ALIAS" A "$ip" '' '' "$restart" '' 'yes'
|
||||
else
|
||||
$BIN/v-delete-dns-record "$user" "$domain" "$webmail_record" "$restart" 'yes'
|
||||
$BIN/v-add-dns-record "$user" "$domain" "$WEBMAIL_ALIAS" A "$ip" '' '' "$restart" '' 'yes'
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$webmail" == "roundcube" ]; then
|
||||
WEBMAIL_TEMPLATE="default"
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
PROXY_TEMPLATE="default"
|
||||
fi
|
||||
# Add webmail configuration to mail domain
|
||||
WEBMAIL_TEMPLATE="default"
|
||||
if [ "$WEB_SYSTEM" = "nginx" ]; then
|
||||
WEBMAIL_TEMPLATE="web_system"
|
||||
fi
|
||||
elif [ -f "$HESTIA/data/templates/mail/$WEB_SYSTEM/$webmail.tpl" ]; then
|
||||
WEBMAIL_TEMPLATE="$webmail"
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
PROXY_TEMPLATE="default_$webmail"
|
||||
fi
|
||||
else
|
||||
WEBMAIL_TEMPLATE="disabled"
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
PROXY_TEMPLATE="default_disabled"
|
||||
fi
|
||||
fi
|
||||
|
||||
add_webmail_config "$WEB_SYSTEM" "${WEBMAIL_TEMPLATE}.tpl"
|
||||
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
add_webmail_config "$PROXY_SYSTEM" "${PROXY_TEMPLATE}.tpl"
|
||||
fi
|
||||
|
||||
# Enable SSL for webmail if available
|
||||
if [ -f $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.crt ] || [ "$SSL" = 'yes' ]; then
|
||||
add_webmail_config "$WEB_SYSTEM" "${WEBMAIL_TEMPLATE}.stpl"
|
||||
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
add_webmail_config "$PROXY_SYSTEM" "${PROXY_TEMPLATE}.stpl"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
WEBMAIL=$(get_object_value 'web' 'DOMAIN' "$domain" "$WEBMAIL")
|
||||
if [ -z "$WEBMAIL" ]; then
|
||||
add_object_key 'mail' 'DOMAIN' "$domain" 'WEBMAIL' 'SSL'
|
||||
fi
|
||||
|
||||
# Set SSL as enabled in configuration
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$WEBMAIL' "$webmail"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ "$restart" = 'yes' ]; then
|
||||
# Restarting web server
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
fi
|
||||
|
||||
# Logging
|
||||
if [ "$quiet" != 'yes' ]; then
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "Webmail access enabled (Domain: $domain)."
|
||||
fi
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,124 @@
|
||||
#!/bin/bash
|
||||
# info: add remote dns domain
|
||||
# options: USER DOMAIN [FLUSH]
|
||||
#
|
||||
# example: v-add-remote-dns-domain admin mydomain.tld yes
|
||||
#
|
||||
# This function synchronise dns domain with the remote server.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
flush=$3
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/remote.sh
|
||||
source $HESTIA/func/remote.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN [FLUSH]'
|
||||
is_format_valid 'user' 'domain'
|
||||
if [ -n "$flush" ]; then
|
||||
is_type_valid "records yes no" "$flush"
|
||||
fi
|
||||
is_system_enabled "$DNS_CLUSTER" 'DNS_CLUSTER'
|
||||
is_procces_running
|
||||
remote_dns_health_check
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Parsing domain record
|
||||
str=$(grep "DOMAIN='$domain'" $USER_DATA/dns.conf 2> /dev/null)
|
||||
if [ -z "$str" ]; then
|
||||
pipe="$HESTIA/data/queue/dns-cluster.pipe"
|
||||
queue_str=$(grep -n "$SCRIPT $1 $2 " $pipe | cut -f1 -d: | head -n1)
|
||||
if [ -n "$queue_str" ]; then
|
||||
sed -i "$queue_str d" $pipe
|
||||
fi
|
||||
exit
|
||||
fi
|
||||
if [ "$DNS_CLUSTER_SYSTEM" = "hestia-zone" ]; then
|
||||
str=$(echo "$str" | sed "s/SLAVE='no'/SLAVE='yes'/g")
|
||||
str=$(echo "$str" | sed "s/SLAVE=''/SLAVE='yes'/g")
|
||||
ip=$(ip addr | grep 'inet ' | grep global | head -n1 | awk '{print $2}' | cut -f1 -d/)
|
||||
source_conf $HESTIA/data/ips/$ip
|
||||
if [ -z $NAT ]; then
|
||||
str=$(echo "$str" | sed "s/MASTER=''/MASTER='$ip'/g")
|
||||
else
|
||||
str=$(echo "$str" | sed "s/MASTER=''/MASTER='$NAT'/g")
|
||||
fi
|
||||
fi
|
||||
|
||||
IFS=$'\n'
|
||||
for cluster in $(grep "SUSPENDED='no'" $HESTIA/conf/dns-cluster.conf); do
|
||||
# Reset user, password and hash vars
|
||||
clear_dns_cluster_settings
|
||||
|
||||
# Parsing remote dns host parameters
|
||||
parse_object_kv_list "$cluster"
|
||||
|
||||
# Parsing domain parameters
|
||||
parse_object_kv_list "$str"
|
||||
|
||||
if [ "$DNS_CLUSTER_SYSTEM" = "hestia-zone" ]; then
|
||||
# Syncing domain data
|
||||
cluster_cmd v-insert-dns-domain $DNS_USER "$str" $HOSTNAME $flush 'no'
|
||||
check_result $? "$HOST connection failed" "$E_CONNECT"
|
||||
|
||||
cluster_cmd v-rebuild-dns-domain $DNS_USER $domain 'yes' 'no'
|
||||
check_result $? "$HOST connection failed" "$E_CONNECT"
|
||||
|
||||
else
|
||||
# Syncing domain data
|
||||
cluster_cmd v-insert-dns-domain $DNS_USER "$str" $HOSTNAME $flush 'no'
|
||||
check_result $? "$HOST connection failed" "$E_CONNECT"
|
||||
|
||||
# Syncing domain records
|
||||
tmp_file="/tmp/vst-sync.$DOMAIN"
|
||||
cluster_file $USER_DATA/dns/$DOMAIN.conf $tmp_file
|
||||
check_result $? "$HOST connection failed" "$E_CONNECT"
|
||||
|
||||
# Inserting synced records
|
||||
cluster_cmd v-insert-dns-records $DNS_USER $DOMAIN $tmp_file 'no'
|
||||
check_result $? "$HOST connection failed" "$E_CONNECT"
|
||||
|
||||
# Rebuilding dns zone
|
||||
cluster_cmd v-rebuild-dns-domain $DNS_USER $domain 'yes' 'no'
|
||||
check_result $? "$HOST connection failed" "$E_CONNECT"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$DNS_CLUSTER_SYSTEM" = "hestia-zone" ]; then
|
||||
rndc notify $domain > /dev/null 2>&1
|
||||
fi
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Updating pipe
|
||||
rm -f $tmpfile
|
||||
pipe="$HESTIA/data/queue/dns-cluster.pipe"
|
||||
str=$(grep -n "$SCRIPT $1 $2 " $pipe | cut -f1 -d: | head -n1)
|
||||
if [ -n "$str" ]; then
|
||||
sed -i "$str d" $pipe
|
||||
fi
|
||||
|
||||
exit
|
@ -0,0 +1,131 @@
|
||||
#!/bin/bash
|
||||
# info: add new remote dns host
|
||||
# options: HOST PORT USER PASSWORD [TYPE] [DNS_USER]
|
||||
#
|
||||
# example: v-add-remote-dns-host slave.your_host.com 8083 admin your_passw0rd
|
||||
#
|
||||
# example: v-add-remote-dns-host slave.your_host.com 8083 api_key ''
|
||||
#
|
||||
# This function adds remote dns server to the dns cluster.
|
||||
# As alternative api_key generated on the slave server.
|
||||
# See v-generate-api-key can be used to connect the remote dns server
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
host=$1
|
||||
HOST=$host
|
||||
port=$2
|
||||
PORT=$port
|
||||
user=$3
|
||||
USER=$user
|
||||
hash=$user
|
||||
HASH=$user
|
||||
password=$4
|
||||
HIDE=4
|
||||
PASSWORD=$password
|
||||
type=${5}
|
||||
TYPE="$type"
|
||||
dns_user=${6-dns-cluster}
|
||||
DNS_USER=$dns_user
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/remote.sh
|
||||
source $HESTIA/func/remote.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ -z "$type" ]; then
|
||||
type='api'
|
||||
TYPE="$type"
|
||||
fi
|
||||
|
||||
args_usage='HOST PORT USER [PASSWORD] [TYPE] [DNS_USER]'
|
||||
check_args '3' "$#" "$args_usage"
|
||||
is_format_valid 'host' 'port' 'dns_user'
|
||||
if [ -z "$password" ]; then
|
||||
is_format_valid 'hash'
|
||||
else
|
||||
is_format_valid 'user'
|
||||
fi
|
||||
is_type_valid "api ssh" "$type"
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_password_valid
|
||||
is_dnshost_new
|
||||
is_dnshost_alive
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
if [ -z "$password" ]; then
|
||||
# Concatentating dns host string
|
||||
str="HOST='$host' PORT='$port' HASH='$hash'"
|
||||
str="$str DNS_USER='$dns_user' TYPE='$type' SUSPENDED='no'"
|
||||
str="$str TIME='$time' DATE='$date'"
|
||||
else
|
||||
# Concatentating dns host string
|
||||
str="HOST='$host' PORT='$port' USER='$user' PASSWORD='$password'"
|
||||
str="$str DNS_USER='$dns_user' TYPE='$type' SUSPENDED='no'"
|
||||
str="$str TIME='$time' DATE='$date'"
|
||||
fi
|
||||
|
||||
# Adding host to dns-cluster.conf
|
||||
echo "$str" >> $HESTIA/conf/dns-cluster.conf
|
||||
chmod 660 $HESTIA/conf/dns-cluster.conf
|
||||
|
||||
# Enabling DNS_CLUSTER
|
||||
if [ -z "$(grep DNS_CLUSTER= $HESTIA/conf/hestia.conf)" ]; then
|
||||
sed -i "s/^STATS_/DNS_CLUSTER='yes'\nSTATS_/g" $HESTIA/conf/hestia.conf
|
||||
else
|
||||
sed -i "s/DNS_CLUSTER=.*/DNS_CLUSTER='yes'/g" $HESTIA/conf/hestia.conf
|
||||
fi
|
||||
|
||||
# Enabling remote dns-cluster queue
|
||||
cluster_cmd v-add-cron-restart-job
|
||||
check_result $? "$HOST connection failed" "$E_CONNECT"
|
||||
|
||||
# Loop trough domains to generate new serial
|
||||
for dns_user in $($BIN/v-list-sys-users plain); do
|
||||
for dns_domain in $($BIN/v-list-dns-domains $dns_user plain | cut -f1); do
|
||||
$BIN/v-rebuild-dns-domain $dns_user $dns_domain "no" "yes"
|
||||
done
|
||||
done
|
||||
|
||||
# Syncing all domains
|
||||
$BIN/v-sync-dns-cluster
|
||||
check_result $? "$HOST sync failed" "$E_CONNECT"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding local dns-cluster cron job
|
||||
cmd="sudo $BIN/v-update-sys-queue dns-cluster"
|
||||
check_cron=$(grep "$cmd" $HESTIA/data/users/admin/cron.conf 2> /dev/null)
|
||||
if [ -z "$check_cron" ] && [ ! -z "$CRON_SYSTEM" ]; then
|
||||
$BIN/v-add-cron-job admin '*/5' '*' '*' '*' '*' "$cmd"
|
||||
fi
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,98 @@
|
||||
#!/bin/bash
|
||||
# info: add remote dns domain record
|
||||
# options: USER DOMAIN ID
|
||||
#
|
||||
# example: v-add-remote-dns-record bob acme.com 23
|
||||
#
|
||||
# This function synchronise dns domain with the remote server.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
id=$3
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/remote.sh
|
||||
source $HESTIA/func/remote.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN ID'
|
||||
is_format_valid 'user' 'domain' 'id'
|
||||
is_system_enabled "$DNS_CLUSTER" 'DNS_CLUSTER'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_valid 'dns' 'DOMAIN' "$domain"
|
||||
is_procces_running
|
||||
remote_dns_health_check
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Parsing record
|
||||
str=$(grep "ID='$id'" $USER_DATA/dns/$domain.conf)
|
||||
if [ -z "$str" ]; then
|
||||
pipe="$HESTIA/data/queue/dns-cluster.pipe"
|
||||
queue_str=$(grep -n "$SCRIPT $1 $2 $3$" $pipe | cut -f1 -d: | head -n1)
|
||||
if [ -n "$queue_str" ]; then
|
||||
sed -i "$queue_str d" $pipe
|
||||
fi
|
||||
exit
|
||||
fi
|
||||
# $DNS_CLUSTER_SYSTEM = "hestia-zone" doesn't need to be uopdated
|
||||
|
||||
if [ "$DNS_CLUSTER_SYSTEM" != "hestia-zone" ]; then
|
||||
IFS=$'\n'
|
||||
for cluster in $(grep "SUSPENDED='no'" $HESTIA/conf/dns-cluster.conf); do
|
||||
|
||||
# Reset user, password and hash vars
|
||||
clear_dns_cluster_settings
|
||||
|
||||
# Parsing remote host parameters
|
||||
parse_object_kv_list "$cluster"
|
||||
|
||||
# Syncing serial
|
||||
str=$(grep "DOMAIN='$domain'" $USER_DATA/dns.conf)
|
||||
# Parsing domain parameters
|
||||
parse_object_kv_list "$str"
|
||||
|
||||
cluster_cmd v-insert-dns-domain $DNS_USER "$str" $HOSTNAME 'domain' 'no'
|
||||
check_result $? "$HOST connection failed (soa sync)" "$E_CONNECT"
|
||||
|
||||
# Syncing record
|
||||
str=$(grep "ID='$id'" $USER_DATA/dns/$domain.conf)
|
||||
cluster_cmd v-insert-dns-record $DNS_USER $domain "$str" 'no'
|
||||
check_result $? "$HOST connection failed (record sync)" "$E_CONNECT"
|
||||
|
||||
# Rebuilding dns zone
|
||||
cluster_cmd v-rebuild-dns-domain $DNS_USER $domain 'yes' 'no'
|
||||
check_result $? "$HOST connection failed (rebuild)" "$E_CONNECT"
|
||||
done
|
||||
fi
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Updating pipe
|
||||
pipe="$HESTIA/data/queue/dns-cluster.pipe"
|
||||
str=$(grep -n "$SCRIPT $1 $2 $3$" $pipe | cut -f1 -d: | head -n1)
|
||||
if [ -n "$str" ]; then
|
||||
sed -i "$str d" $pipe
|
||||
fi
|
||||
|
||||
exit
|
@ -0,0 +1,49 @@
|
||||
#!/bin/bash
|
||||
# info: add IP address to API allow list
|
||||
# options: IP
|
||||
#
|
||||
# example: v-add-sys-api-ip 1.1.1.1
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
ip46=${1// /}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'IP'
|
||||
is_format_valid 'ip46'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ "$API_ALLOWED_IP" != "" ]; then
|
||||
$BIN/v-change-sys-config-value 'API_ALLOWED_IP' "$API_ALLOWED_IP,$ip46"
|
||||
else
|
||||
$BIN/v-change-sys-config-value 'API_ALLOWED_IP' "$ip46"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Warning" "System" "Added new IP address added to Allowed IP API (IP: $ip46)"
|
||||
log_event "$OK" "$ARGUMENTS"
|
@ -0,0 +1,109 @@
|
||||
#!/bin/bash
|
||||
# Add php dependencies to Hestia
|
||||
# options: [MODE]
|
||||
#
|
||||
# This function install PHPMailer and quoteshellarg as via composer
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
# upgrade config file
|
||||
source "$HESTIA/install/upgrade/upgrade.conf"
|
||||
|
||||
MODE=$1
|
||||
user="admin"
|
||||
|
||||
PM_INSTALL_DIR="$HESTIA/web/inc"
|
||||
QUICK_INSTALL_DIR="$HESTIA/web/src"
|
||||
COMPOSER_BIN="$HOMEDIR/$user/.composer/composer"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Checking root permissions
|
||||
if [ "x$(id -u)" != 'x0' ]; then
|
||||
echo "ERROR: v-add-sys-dependencies can be run executed only by root user"
|
||||
exit 10
|
||||
fi
|
||||
|
||||
# Ensure that $HESTIA (/usr/local/hestia/) and other variables are valid.
|
||||
if [ -z "$HESTIA" ]; then
|
||||
HESTIA="/usr/local/hestia"
|
||||
fi
|
||||
|
||||
if [ -z "$HOMEDIR" ] || [ -z "$HESTIA_INSTALL_DIR" ]; then
|
||||
echo "ERROR: Environment variables not present, installation aborted."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Ensure that Composer is installed for the user before continuing as it is a dependency of the PHPMailer.
|
||||
if [ ! -f "$COMPOSER_BIN" ]; then
|
||||
$BIN/v-add-user-composer "$user"
|
||||
if [ $? -ne 0 ]; then
|
||||
$BIN/v-add-user-notification admin 'Composer installation failed!' '<p class="u-text-bold">Hestia will not work without Composer.</p><p>Please try running the installer manually from a shell session:<br><code>v-add-sys-dependencies</code></p><p>If this continues, <a href="https://github.com/hestiacp/hestiacp/issues" target="_blank">open an issue on GitHub</a>.</p>'
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
cd "$PM_INSTALL_DIR"
|
||||
rm --recursive --force ${PM_INSTALL_DIR}/vendor
|
||||
mkdir -p ${PM_INSTALL_DIR}/vendor
|
||||
chown $user: -R ${PM_INSTALL_DIR}/vendor
|
||||
|
||||
openssl_installed=$(/usr/local/hestia/php/bin/php -m | grep openssl)
|
||||
if [ -z "$openssl_installed" ]; then
|
||||
COMPOSER_HOME="$HOMEDIR/$user/.config/composer" user_exec /usr/bin/php $COMPOSER_BIN --quiet --no-dev install
|
||||
else
|
||||
COMPOSER_HOME="$HOMEDIR/$user/.config/composer" user_exec $HESTIA_PHP $COMPOSER_BIN --quiet --no-dev install
|
||||
fi
|
||||
|
||||
# Check if installation was successful, if not abort script and throw error message notification and clean-up
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: PHPMailer installation failed!"
|
||||
echo "Please report this to our development team:"
|
||||
echo "https://github.com/hestiacp/hestiacp/issues"
|
||||
$BIN/v-add-user-notification admin 'Hestia PHP dependencies installation failed!' '<p>Please <a href="https://github.com/hestiacp/hestiacp/issues" target="_blank">open an issue on GitHub</a> to report this to our development team.</p>'
|
||||
# Installation failed, clean up files
|
||||
rm --recursive --force ${PM_INSTALL_DIR}/vendor
|
||||
$BIN/v-change-sys-config-value 'USE_SERVER_SMTP' 'n'
|
||||
$BIN/v-log-action "system" "Error" "Plugins" "PHP dependencies installation failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$QUICK_INSTALL_DIR"
|
||||
rm --recursive --force ${QUICK_INSTALL_DIR}/vendor
|
||||
mkdir -p ${QUICK_INSTALL_DIR}/vendor
|
||||
chown $user: -R ${QUICK_INSTALL_DIR}/vendor
|
||||
|
||||
if [ -z "$openssl_installed" ]; then
|
||||
COMPOSER_HOME="$HOMEDIR/$user/.config/composer" user_exec /usr/bin/php $COMPOSER_BIN --quiet --no-dev install
|
||||
else
|
||||
COMPOSER_HOME="$HOMEDIR/$user/.config/composer" user_exec $HESTIA_PHP $COMPOSER_BIN --quiet --no-dev install
|
||||
fi
|
||||
|
||||
# Set permissions
|
||||
chown root: -R "${PM_INSTALL_DIR}/vendor"
|
||||
chown root: -R "${QUICK_INSTALL_DIR}/vendor"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Logging #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
$BIN/v-log-action "system" "Info" "Plugins" "PHPMailer enabled (Version: $pm_v)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
@ -0,0 +1,119 @@
|
||||
#!/bin/bash
|
||||
# info: add file manager functionality to Hestia Control Panel
|
||||
# options: [MODE]
|
||||
#
|
||||
# This function installs the File Manager on the server
|
||||
# for access through the Web interface.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
# load config file
|
||||
source_conf "$HESTIA/install/upgrade/upgrade.conf"
|
||||
|
||||
MODE=$1
|
||||
user="admin"
|
||||
|
||||
FM_INSTALL_DIR="$HESTIA/web/fm"
|
||||
FM_FILE="filegator_latest"
|
||||
FM_URL="https://github.com/filegator/static/raw/master/builds/filegator_latest.zip"
|
||||
COMPOSER_BIN="$HOMEDIR/$user/.composer/composer"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Checking root permissions
|
||||
if [ "x$(id -u)" != 'x0' ]; then
|
||||
echo "ERROR: v-add-sys-filemanager can be run executed only by root user"
|
||||
exit 10
|
||||
fi
|
||||
|
||||
# Ensure that $HESTIA (/usr/local/hestia/) and other variables are valid.
|
||||
if [ -z "$HESTIA" ]; then
|
||||
HESTIA="/usr/local/hestia"
|
||||
fi
|
||||
|
||||
if [ -z "$HOMEDIR" ] || [ -z "$HESTIA_INSTALL_DIR" ]; then
|
||||
echo "ERROR: Environment variables not present, installation aborted."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Ensure that Composer is installed for the user before continuing as it is a dependency of the File Manager.
|
||||
if [ ! -f "$COMPOSER_BIN" ]; then
|
||||
$BIN/v-add-user-composer "$user"
|
||||
if [ $? -ne 0 ]; then
|
||||
$BIN/v-add-user-notification admin 'Composer installation failed!' '<p class="u-text-bold">The File Manager will not work without Composer.</p><p>Please try running the installer manually from a shell session:<br><code>v-add-sys-filemanager</code></p><p>If this continues, <a href="https://github.com/hestiacp/hestiacp/issues" target="_blank">open an issue on GitHub</a>.</p>'
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
openssl_installed=$(/usr/local/hestia/php/bin/php -m | grep openssl)
|
||||
|
||||
rm --recursive --force "$FM_INSTALL_DIR"
|
||||
mkdir -p "$FM_INSTALL_DIR"
|
||||
cd "$FM_INSTALL_DIR"
|
||||
|
||||
[ ! -f "${FM_INSTALL_DIR}/${FM_FILE}" ] && wget "$FM_URL" --quiet -O "${FM_INSTALL_DIR}/${FM_FILE}.zip"
|
||||
|
||||
unzip -qq "${FM_INSTALL_DIR}/${FM_FILE}.zip"
|
||||
mv --force ${FM_INSTALL_DIR}/filegator/* "${FM_INSTALL_DIR}"
|
||||
rm --recursive --force ${FM_INSTALL_DIR}/${FM_FILE}
|
||||
[[ -f "${FM_INSTALL_DIR}/${FM_FILE}" ]] && rm "${FM_INSTALL_DIR}/${FM_FILE}"
|
||||
|
||||
cp --recursive --force ${HESTIA_INSTALL_DIR}/filemanager/filegator/* "${FM_INSTALL_DIR}"
|
||||
|
||||
chown $user: -R "${FM_INSTALL_DIR}"
|
||||
|
||||
if [ -z "$openssl_installed" ]; then
|
||||
COMPOSER_HOME="$HOMEDIR/$user/.config/composer" user_exec /usr/bin/php $COMPOSER_BIN --quiet --no-dev install
|
||||
else
|
||||
COMPOSER_HOME="$HOMEDIR/$user/.config/composer" user_exec /usr/local/hestia/php/bin/php $COMPOSER_BIN --quiet --no-dev install
|
||||
fi
|
||||
|
||||
# Check if installation was successful, if not abort script and throw error message notification and clean-up
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: File Manager installation failed!"
|
||||
echo "Please report this to our development team:"
|
||||
echo "https://github.com/hestiacp/hestiacp/issues"
|
||||
$BIN/v-add-user-notification admin 'File Manager installation failed!' '<p>Please <a href="https://github.com/hestiacp/hestiacp/issues" target="_blank">open an issue on GitHub</a> to report this to our development team.</p>'
|
||||
# Installation failed, clean up files
|
||||
rm --recursive --force ${FM_INSTALL_DIR}
|
||||
$BIN/v-change-sys-config-value 'FILE_MANAGER' 'false'
|
||||
$BIN/v-log-action "system" "Error" "Plugins" "File Manager installation failed (Version: $fm_v)."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Add configuration file
|
||||
cp -f $HESTIA_INSTALL_DIR/filemanager/filegator/configuration.php $HESTIA/web/fm/configuration.php
|
||||
|
||||
echo "$fm_v" > "${FM_INSTALL_DIR}/version"
|
||||
# Set permissions
|
||||
chown root: -R "${FM_INSTALL_DIR}"
|
||||
chown $user: "${FM_INSTALL_DIR}/private"
|
||||
chown $user: "${FM_INSTALL_DIR}/private/logs"
|
||||
chown $user: "${FM_INSTALL_DIR}/repository"
|
||||
|
||||
$BIN/v-change-sys-config-value 'FILE_MANAGER' 'true'
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Logging #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
$BIN/v-log-action "system" "Info" "Plugins" "File Manager enabled (Version: $fm_v)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
@ -0,0 +1,56 @@
|
||||
#!/bin/bash
|
||||
# info: add system firewall
|
||||
# options: NONE
|
||||
#
|
||||
# example: v-add-sys-firewall
|
||||
#
|
||||
# This function enables the system firewall.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ "$FIREWALL_SYSTEM" = 'iptables' ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding default ruleset
|
||||
if [ -z "$(ls -A $HESTIA/data/firewall 2> /dev/null)" ]; then
|
||||
cp -rf $HESTIA_COMMON_DIR/firewall $HESTIA/data/
|
||||
rm -f $HESTIA/data/firewall/ipset/blacklist.sh $HESTIA/data/firewall/ipset/blacklist.ipv6.sh
|
||||
fi
|
||||
|
||||
# Updating FIREWAL_SYSTEM value
|
||||
$BIN/v-change-sys-config-value "FIREWALL_SYSTEM" "iptables"
|
||||
|
||||
# Updating firewall rules
|
||||
$BIN/v-update-firewall
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "Firewall" "System firewall enabled."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,234 @@
|
||||
#!/bin/bash
|
||||
# info: add system IP address
|
||||
# options: IP NETMASK [INTERFACE] [USER] [IP_STATUS] [IP_NAME] [NAT_IP]
|
||||
#
|
||||
# example: v-add-sys-ip 203.0.113.1 255.255.255.0
|
||||
#
|
||||
# This function adds IP address into a system. It also creates rc scripts. You
|
||||
# can specify IP name which will be used as root domain for temporary aliases.
|
||||
# For example, if you set a1.myhosting.com as name, each new domain created on
|
||||
# this IP will automatically receive alias $domain.a1.myhosting.com. Of course
|
||||
# you must have wildcard record *.a1.myhosting.com pointed to IP. This feature
|
||||
# is very handy when customer wants to test domain before dns migration.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
ip="${1// /}"
|
||||
netmask="$2"
|
||||
|
||||
# Get interface name
|
||||
# First try to detect which interface the IP address resides on
|
||||
iface="$(ip -d -j addr show | jq --arg IP "$ip" -r '.[] | if .addr_info[].local == $IP then .ifname else empty end')"
|
||||
# If that fails, detect the default interface as a fallback
|
||||
if [ -z "$iface" ]; then
|
||||
iface="$(ip -d -j route show | jq -r '.[] | if .dst == "default" then .dev else empty end')"
|
||||
fi
|
||||
|
||||
iface="${3-$iface}"
|
||||
user="${4-admin}"
|
||||
ip_status="${5-shared}"
|
||||
ip_name="$6"
|
||||
nat_ip="$7"
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'IP NETMASK [INTERFACE] [USER] [STATUS] [NAME] [NATED_IP]'
|
||||
is_format_valid 'ip' 'netmask' 'iface' 'user' 'ip_status'
|
||||
is_ip_free
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
if [ -n "$ip_name" ]; then
|
||||
is_format_valid 'ip_name'
|
||||
fi
|
||||
if [ -n "$nat_ip" ]; then
|
||||
is_format_valid 'nat_ip'
|
||||
fi
|
||||
if [ "$user" != "admin" ]; then
|
||||
ip_status="dedicated"
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
cidr="$(convert_netmask "$netmask")"
|
||||
broadcast="$(get_broadcast "$ip" "$netmask")"
|
||||
|
||||
sys_ip_check="$(ip addr | grep -w "$ip")"
|
||||
if [ -z "$sys_ip_check" ]; then
|
||||
# Adding system IP
|
||||
ip addr add "$ip/$cidr" dev "$iface" broadcast "$broadcast" label "$iface"
|
||||
|
||||
# Check if netplan is in use and generate configuration file
|
||||
if [ -n "$(netplan generate --mapping "$iface" 2> /dev/null | grep networkd)" ]; then
|
||||
netplan="true"
|
||||
else
|
||||
netplan="false"
|
||||
fi
|
||||
|
||||
if [ "$netplan" = "true" ]; then
|
||||
if [ -f "/etc/netplan/60-hestia.yaml" ]; then
|
||||
sys_ip=" - $ip/$cidr"
|
||||
else
|
||||
sys_ip="# Added by Hestia, please do not edit the file manually!"
|
||||
sys_ip="$sys_ip\nnetwork:"
|
||||
sys_ip="$sys_ip\n version: 2"
|
||||
sys_ip="$sys_ip\n renderer: networkd"
|
||||
sys_ip="$sys_ip\n ethernets:"
|
||||
sys_ip="$sys_ip\n $iface:"
|
||||
sys_ip="$sys_ip\n addresses:"
|
||||
sys_ip="$sys_ip\n - $ip/$cidr"
|
||||
fi
|
||||
IFS='%'
|
||||
echo -e "$sys_ip" >> /etc/netplan/60-hestia.yaml
|
||||
unset IFS
|
||||
else
|
||||
sys_ip="\n# Added by Hestia Control Panel"
|
||||
sys_ip="$sys_ip\nauto $iface"
|
||||
sys_ip="$sys_ip\niface $iface inet static"
|
||||
sys_ip="$sys_ip\naddress $ip"
|
||||
sys_ip="$sys_ip\nnetmask $netmask"
|
||||
echo -e $sys_ip >> /etc/network/interfaces
|
||||
fi
|
||||
fi
|
||||
|
||||
# Generating timestamp
|
||||
new_timestamp
|
||||
|
||||
# Adding Hestia IP
|
||||
echo "OWNER='$user'
|
||||
STATUS='$ip_status'
|
||||
NAME='$ip_name'
|
||||
U_SYS_USERS=''
|
||||
U_WEB_DOMAINS='0'
|
||||
INTERFACE='$iface'
|
||||
NETMASK='$netmask'
|
||||
NAT='$nat_ip'
|
||||
TIME='$time'
|
||||
DATE='$date'" > $HESTIA/data/ips/$ip
|
||||
chmod 660 $HESTIA/data/ips/$ip
|
||||
|
||||
# WEB support
|
||||
if [ -n "$WEB_SYSTEM" ]; then
|
||||
web_conf="/etc/$WEB_SYSTEM/conf.d/$ip.conf"
|
||||
rm -f "$web_conf"
|
||||
|
||||
if [ "$WEB_SYSTEM" = 'httpd' ] || [ "$WEB_SYSTEM" = 'apache2' ]; then
|
||||
if [ -z "$(/usr/sbin/apachectl -v | grep Apache/2.4)" ]; then
|
||||
echo "NameVirtualHost $ip:$WEB_PORT" > "$web_conf"
|
||||
fi
|
||||
echo "Listen $ip:$WEB_PORT" >> "$web_conf"
|
||||
cat $HESTIA_INSTALL_DIR/apache2/unassigned.conf >> "$web_conf"
|
||||
sed -i 's/directIP/'$ip'/g' "$web_conf"
|
||||
sed -i 's/directPORT/'$WEB_PORT'/g' "$web_conf"
|
||||
|
||||
elif [ "$WEB_SYSTEM" = 'nginx' ]; then
|
||||
cp -f $HESTIA_INSTALL_DIR/nginx/unassigned.inc "$web_conf"
|
||||
sed -i 's/directIP/'$ip'/g' "$web_conf"
|
||||
process_http2_directive "$web_conf"
|
||||
fi
|
||||
|
||||
if [ "$WEB_SSL" = 'mod_ssl' ]; then
|
||||
if [ -z "$(/usr/sbin/apachectl -v | grep Apache/2.4)" ]; then
|
||||
sed -i "1s/^/NameVirtualHost $ip:$WEB_SSL_PORT\n/" "$web_conf"
|
||||
fi
|
||||
sed -i "1s/^/Listen $ip:$WEB_SSL_PORT\n/" "$web_conf"
|
||||
sed -i 's/directSSLPORT/'$WEB_SSL_PORT'/g' "$web_conf"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Proxy support
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
cat $WEBTPL/$PROXY_SYSTEM/proxy_ip.tpl \
|
||||
| sed -e "s/%ip%/$ip/g" \
|
||||
-e "s/%web_port%/$WEB_PORT/g" \
|
||||
-e "s/%proxy_port%/$PROXY_PORT/g" \
|
||||
-e "s/%proxy_ssl_port%/$PROXY_SSL_PORT/g" \
|
||||
> /etc/$PROXY_SYSTEM/conf.d/$ip.conf
|
||||
|
||||
process_http2_directive "/etc/$PROXY_SYSTEM/conf.d/$ip.conf"
|
||||
|
||||
# mod_extract_forwarded
|
||||
fw_conf="/etc/$WEB_SYSTEM/conf.d/mod_extract_forwarded.conf"
|
||||
if [ -e "$fw_conf" ]; then
|
||||
ips=$(grep 'MEFaccept ' "$fw_conf" | grep -v '#' | head -n1)
|
||||
sed -i "s/$ips/$ips $ip/g" "$fw_conf"
|
||||
fi
|
||||
|
||||
# mod_rpaf
|
||||
rpaf_conf="/etc/$WEB_SYSTEM/mods-enabled/rpaf.conf"
|
||||
if [ -e "$rpaf_conf" ]; then
|
||||
rpaf_str="$(grep RPAFproxy_ips "$rpaf_conf")"
|
||||
[ -z "$rpaf_str" ] && sed -i 's|</IfModule>|RPAFproxy_ips\n</IfModule>|' "$rpaf_conf" && rpaf_str='RPAFproxy_ips'
|
||||
rpaf_str="$rpaf_str $ip"
|
||||
sed -i "s/.*RPAFproxy_ips.*/$rpaf_str/" "$rpaf_conf"
|
||||
fi
|
||||
|
||||
# mod_remoteip
|
||||
remoteip_conf="/etc/$WEB_SYSTEM/mods-enabled/remoteip.conf"
|
||||
if [ -e "$remoteip_conf" ]; then
|
||||
if [ "$(grep -ic "$ip" "$remoteip_conf")" -eq "0" ]; then
|
||||
sed -i "s/<\/IfModule>/RemoteIPInternalProxy $ip\n<\/IfModule>/g" "$remoteip_conf"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Updating user counters
|
||||
increase_user_value "$user" '$IP_OWNED'
|
||||
if [ "$user" = 'admin' ]; then
|
||||
if [ "$ip_status" = 'shared' ]; then
|
||||
for hestia_user in $($BIN/v-list-sys-users plain); do
|
||||
increase_user_value "$hestia_user" '$IP_AVAIL'
|
||||
done
|
||||
else
|
||||
increase_user_value 'admin' '$IP_AVAIL'
|
||||
fi
|
||||
else
|
||||
increase_user_value "$user" '$IP_AVAIL'
|
||||
increase_user_value 'admin' '$IP_AVAIL'
|
||||
fi
|
||||
|
||||
# Restarting web server
|
||||
$BIN/v-restart-web
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
|
||||
# Restarting proxy server
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
$BIN/v-restart-proxy
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
fi
|
||||
|
||||
# Restarting firewall
|
||||
if [ -n "$FIREWALL_SYSTEM" ]; then
|
||||
$BIN/v-update-firewall
|
||||
fi
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "Network" "Added new IP address to the system (IP: $ip)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,120 @@
|
||||
#!/bin/bash
|
||||
# info: enables support for single sign on phpMyAdmin
|
||||
# options: [mode]
|
||||
#
|
||||
# example: v-add-sys-pma-sso
|
||||
#
|
||||
# This function enables support for SSO to phpMyAdmin
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
MODE=$1
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
PMA_INSTALL="/usr/share/phpmyadmin"
|
||||
PMA_CONFIG="/etc/phpmyadmin"
|
||||
|
||||
|
||||
WWW_USER="www-data"
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
WWW_USER="apache"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
# Checking root permissions
|
||||
if [ "x$(id -u)" != 'x0' ]; then
|
||||
echo "Error: Script can be run executed only by root"
|
||||
exit 10
|
||||
fi
|
||||
|
||||
if [ -n "$PHPMYADMIN_KEY" ] && [ "$PHPMYADMIN_KEY" != "" ]; then
|
||||
echo "Error: SSO has been installed before to reenable it please run v-delete-sys-pma-sso first"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -f "/usr/share/phpmyadmin/hestia-sso.php" ]; then
|
||||
echo "Error: hestia-sso.php is already installed"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ -f "/usr/local/hesta/web/api/index.php" ]; then
|
||||
echo "Error: API script not installed"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ "API_SYSTEM" = "0" ]; then
|
||||
echo "Error: API is not enabled"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generate the keys to secure everything
|
||||
phpmyadminkey=$(generate_password)
|
||||
apikey=$($BIN/v-add-access-key 'admin' 'phpmyadmin-sso' 'phpMyAdmin' 'plain')
|
||||
|
||||
# copy config dir to /usr/share/phpmyadmin/
|
||||
cp -f $HESTIA_COMMON_DIR/phpmyadmin/hestia-sso.php $PMA_INSTALL/hestia-sso.php
|
||||
chmod 640 $PMA_INSTALL/hestia-sso.php
|
||||
chown root:$WWW_USER $PMA_INSTALL/hestia-sso.php
|
||||
|
||||
sed -i "s/%PHPMYADMIN_KEY%/$phpmyadminkey/g" $PMA_INSTALL/hestia-sso.php
|
||||
sed -i "s/%API_KEY%/$apikey/g" $PMA_INSTALL/hestia-sso.php
|
||||
sed -i "s/%API_HOST_NAME%/$(hostname)/g" $PMA_INSTALL/hestia-sso.php
|
||||
sed -i "s/%API_HESTIA_PORT%/$BACKEND_PORT/g" $PMA_INSTALL/hestia-sso.php
|
||||
|
||||
# Check if config already contains the keys
|
||||
touch $PMA_CONFIG/hestia-sso.inc.php
|
||||
chmod 640 $PMA_CONFIG/hestia-sso.inc.php
|
||||
chown root:$WWW_USER $PMA_CONFIG/hestia-sso.inc.php
|
||||
|
||||
echo "<?php
|
||||
if(isset(\$_GET['hestia_token']) || isset(\$_COOKIE['SignonSession'])){
|
||||
\$cfg['Servers'][\$i]['auth_type'] = 'signon';
|
||||
\$cfg['Servers'][\$i]['SignonSession'] = 'SignonSession';
|
||||
\$cfg['Servers'][\$i]['SignonURL'] = 'hestia-sso.php';
|
||||
\$cfg['Servers'][\$i]['LogoutURL'] = 'hestia-sso.php?logout=1';
|
||||
}
|
||||
?>" >> $PMA_CONFIG/hestia-sso.inc.php
|
||||
|
||||
file=$(cat $PMA_CONFIG/config.inc.php)
|
||||
if ! [[ "$file" =~ hestia-sso.inc.php ]]; then
|
||||
if [[ $file =~ "//Add Hestia SSO code here" ]]; then
|
||||
sed -i "s|//Add Hestia SSO code here|//Add Hestia SSO code here\n include ('$PMA_CONFIG/hestia-sso.inc.php');|g" $PMA_CONFIG/config.inc.php
|
||||
else
|
||||
echo "include ('$PMA_CONFIG/hestia-sso.inc.php');" >> $PMA_CONFIG/config.inc.php
|
||||
fi
|
||||
fi
|
||||
|
||||
$BIN/v-change-sys-config-value 'PHPMYADMIN_KEY' "$phpmyadminkey"
|
||||
|
||||
if [ -z "$(echo $API_ALLOWED_IP | grep 127.0.0.1)" ]; then
|
||||
$BIN/v-add-sys-api-ip "127.0.0.1"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Logging #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ "$MODE" != "quiet" ]; then
|
||||
echo "PMA Hestia-SSO plugin has been successfully installed"
|
||||
fi
|
||||
$BIN/v-log-action "system" "Info" "Plugins" "phpMyAdmin Single Sign-On has been enabled."
|
||||
log_event "$OK" "$ARGUMENTS"
|
@ -0,0 +1,106 @@
|
||||
#!/bin/bash
|
||||
# info: add system quota
|
||||
# options: NONE
|
||||
#
|
||||
# example: v-add-sys-quota
|
||||
#
|
||||
# This function enables filesystem quota on /home partition
|
||||
# Some kernels do require additional packages to be installed first
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variable & Function #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Ensure that quota kernel modules are installed
|
||||
kernel_module_check=$(find /lib/modules/$(uname -r) -type f -name '*quota_v*.ko*' | egrep '.*' && [ $? -eq 0 ])
|
||||
if [ -z "$kernel_module_check" ]; then
|
||||
# Install kernel modules for quota support.
|
||||
# Requires reboot to activate updated kernel.
|
||||
echo "Installing required kernel modules for quota support..."
|
||||
reboot_req="Y"
|
||||
apt-get -qq install linux-image-extra-virtual -y
|
||||
check_result $? "kernel module installation failed" "$E_UPDATE"
|
||||
fi
|
||||
|
||||
# Checking quota package
|
||||
quota=$(which --skip-alias --skip-functions quota 2> /dev/null)
|
||||
if [ $? -ne 0 ]; then
|
||||
if [ -f "/etc/redhat-release" ]; then
|
||||
dnf -y install quota > /dev/null 2>&1
|
||||
else
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get -y install quota > /dev/null 2>&1
|
||||
fi
|
||||
check_result $? "quota package installation failed" "$E_UPDATE"
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding group and user quota on /home partition
|
||||
mnt=$(df -P /home | awk '{print $6}' | tail -n1)
|
||||
lnr=$(cat -n /etc/fstab | grep -v "#" | awk '{print $1,$3}' | grep "$mnt$" | cut -f 1 -d ' ')
|
||||
opt=$(sed -n ${lnr}p /etc/fstab | awk '{print $4}')
|
||||
fnd='usrquota\|grpquota\|usrjquota=aquota.user\|grpjquota=aquota.group\|jqfmt=vfsv0'
|
||||
if [ $(echo $opt | tr ',' '\n' | grep -x $fnd | wc -l) -ne 5 ]; then
|
||||
old=$(echo $(echo $opt | tr ',' '\n' | grep -v 'usrquota\|grpquota\|usrjquota=\|grpjquota=\|jqfmt=') | tr ' ' ',')
|
||||
new='usrquota,grpquota,usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv0'
|
||||
sed -i "$lnr s/$opt/$old,$new/" /etc/fstab
|
||||
mount -o remount "$mnt"
|
||||
fi
|
||||
|
||||
# Adding v2 group and user quota index
|
||||
if [ ! -e "$mnt/aquota.user" ] || [ ! -e "$mnt/aquota.group" ]; then
|
||||
quotacheck -avcugm > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
# Adding quotacheck on reboot
|
||||
touch /forcequotacheck
|
||||
|
||||
# Adding cron job
|
||||
echo '#!/bin/bash' > /etc/cron.daily/quotacheck
|
||||
echo 'touch /forcequotacheck' >> /etc/cron.daily/quotacheck
|
||||
chmod a+x /etc/cron.daily/quotacheck
|
||||
|
||||
# Enabling group and user quota
|
||||
if [ -n "$(quotaon -pa | grep " $mnt " | grep 'user\|group' | grep 'is off')" ]; then
|
||||
quotaon -v $mnt
|
||||
check_result $? "quota can't be enabled in $mnt" "$E_DISK"
|
||||
fi
|
||||
|
||||
# Updating hestia.conf value
|
||||
if [ -z "$(grep DISK_QUOTA $HESTIA/conf/hestia.conf)" ]; then
|
||||
echo "DISK_QUOTA='yes'" >> $HESTIA/conf/hestia.conf
|
||||
else
|
||||
sed -i "s/DISK_QUOTA=.*/DISK_QUOTA='yes'/g" $HESTIA/conf/hestia.conf
|
||||
fi
|
||||
|
||||
# Rebuilding user quota
|
||||
for user in $($BIN/v-list-sys-users plain); do
|
||||
$BIN/v-update-user-quota "$user"
|
||||
done
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "Plugins" "System Quota enforcement enabled."
|
||||
log_history "system quota enforcement enabled"
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,216 @@
|
||||
#!/bin/bash
|
||||
# info: Install Roundcube webmail client
|
||||
# options: [MODE]
|
||||
#
|
||||
# This function installs the Roundcube webmail client.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
source $HESTIA/func/db.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
# upgrade config file
|
||||
source "$HESTIA/install/upgrade/upgrade.conf"
|
||||
|
||||
MODE=$2
|
||||
UPDATE="no"
|
||||
# Version and Download paths
|
||||
RC_FILE="roundcubemail-$rc_v-complete.tar.gz"
|
||||
RC_EXTRACT="roundcubemail-$rc_v"
|
||||
# Downloading full version
|
||||
RC_URL="https://github.com/roundcube/roundcubemail/releases/download/$rc_v/roundcubemail-$rc_v-complete.tar.gz"
|
||||
|
||||
# Folder paths
|
||||
RC_INSTALL_DIR="/var/lib/roundcube"
|
||||
RC_CONFIG_DIR="/etc/roundcube"
|
||||
RC_LOG="/var/log/roundcube"
|
||||
|
||||
WWW_USER="www-data"
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
WWW_USER="apache"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Checking root permissions
|
||||
if [ "x$(id -u)" != 'x0' ]; then
|
||||
echo "ERROR: v-add-sys-roundcube can be run executed only by root user"
|
||||
exit 10
|
||||
fi
|
||||
|
||||
# Ensure that $HESTIA (/usr/local/hestia/) and other variables are valid.
|
||||
if [ -z "$HESTIA" ]; then
|
||||
HESTIA="/usr/local/hestia"
|
||||
fi
|
||||
|
||||
if [ -z "$HOMEDIR" ] || [ -z "$HESTIA_COMMON_DIR" ]; then
|
||||
echo "ERROR: Environment variables not present, installation aborted."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ -z "$(echo "$DB_SYSTEM" | grep -w 'mysql')" ]; then
|
||||
echo "ERROR: Mysql not available. Installation aborted"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ -d "/usr/share/roundcube" ]; then
|
||||
echo "ERROR: Install done from apt source, unable to continue"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Get current version
|
||||
if [ -f "/var/lib/roundcube/index.php" ]; then
|
||||
version=$(cat $RC_INSTALL_DIR/index.php | grep -o -E '[0-9].[0-9].[0-9]+' | head -1)
|
||||
if [ "$version" == "$rc_v" ]; then
|
||||
echo "Error: Installed version ($version) is equal to the available version ($rc_v)"
|
||||
exit 2
|
||||
else
|
||||
UPDATE="yes"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ "$UPDATE" == "no" ]; then
|
||||
rm -f -r $RC_INSTALL_DIR
|
||||
rm -f -r $RC_CONFIG_DIR
|
||||
|
||||
mkdir -p $RC_INSTALL_DIR/
|
||||
mkdir -p $RC_CONFIG_DIR/
|
||||
|
||||
cd "$RC_INSTALL_DIR"
|
||||
[ ! -f "${RC_INSTALL_DIR}/${RC_FILE}" ] && wget "$RC_URL" --retry-connrefused --quiet -O "${RC_INSTALL_DIR}/${RC_FILE}"
|
||||
|
||||
tar xzf $RC_FILE
|
||||
cp -rT $RC_EXTRACT $RC_INSTALL_DIR
|
||||
|
||||
# Delete old config folder
|
||||
cp $RC_INSTALL_DIR/config/defaults.inc.php $RC_CONFIG_DIR/defaults.inc.php
|
||||
rm -f -r $RC_INSTALL_DIR/config/
|
||||
ln -s $RC_CONFIG_DIR/ ./config
|
||||
# Replace with Hestia config
|
||||
cp -f $HESTIA_COMMON_DIR/roundcube/main.inc.php $RC_CONFIG_DIR/config.inc.php
|
||||
cp -f $HESTIA_COMMON_DIR/roundcube/mimetypes.php $RC_CONFIG_DIR/mimetypes.php
|
||||
chmod 644 $RC_CONFIG_DIR/*.php
|
||||
|
||||
cp -f $HESTIA_COMMON_DIR/roundcube/hestia.php $RC_INSTALL_DIR/plugins/password/drivers/
|
||||
mkdir -p $RC_CONFIG_DIR/plugins/password
|
||||
mkdir -p $RC_CONFIG_DIR/plugins/newmail_notifier
|
||||
mkdir -p $RC_CONFIG_DIR/plugins/zipdownload
|
||||
|
||||
# Allow changes to the respective config / Create symlinks to /etc/roundcube/
|
||||
cp -f $HESTIA_COMMON_DIR/roundcube/config.inc.php $RC_CONFIG_DIR/plugins/password/config.inc.php
|
||||
ln -s $RC_CONFIG_DIR/plugins/password/config.inc.php ./plugins/password/config.inc.php
|
||||
cp -f $HESTIA_COMMON_DIR/roundcube/plugins/config_newmail_notifier.inc.php $RC_CONFIG_DIR/plugins/newmail_notifier/config.inc.php
|
||||
ln -s $RC_CONFIG_DIR/plugins/newmail_notifier/config.inc.php ./plugins/newmail_notifier/config.inc.php
|
||||
cp -f $HESTIA_COMMON_DIR/roundcube/plugins/config_zipdownload.inc.php $RC_CONFIG_DIR/plugins/zipdownload/config.inc.php
|
||||
ln -s $RC_CONFIG_DIR/plugins/zipdownload/config.inc.php ./plugins/zipdownload/config.inc.php
|
||||
|
||||
# Set up correct permissions roundcube
|
||||
chown -R root:$WWW_USER $RC_CONFIG_DIR/
|
||||
chmod 751 -R $RC_CONFIG_DIR
|
||||
chmod 644 $RC_CONFIG_DIR/config.inc.php
|
||||
chmod 644 $RC_CONFIG_DIR/plugins/password/config.inc.php
|
||||
chmod 644 $RC_CONFIG_DIR/plugins/newmail_notifier/config.inc.php
|
||||
chmod 644 $RC_CONFIG_DIR/plugins/zipdownload/config.inc.php
|
||||
|
||||
# Add robots.txt
|
||||
echo "User-agent: *" > /var/lib/roundcube/robots.txt
|
||||
echo "Disallow: /" >> /var/lib/roundcube/robots.txt
|
||||
|
||||
chown -R root:$WWW_USER $RC_INSTALL_DIR
|
||||
|
||||
# Log file
|
||||
if [ ! -d $RC_LOG ]; then
|
||||
mkdir $RC_LOG
|
||||
fi
|
||||
chown apache:$WWW_USER $RC_LOG
|
||||
chmod 751 $RC_LOG
|
||||
|
||||
if [ ! -z "$(echo "$DB_SYSTEM" | grep -E 'mysql|pgsql')" ]; then
|
||||
host='localhost'
|
||||
database='roundcube'
|
||||
dbuser="$database"
|
||||
dbpass=$(generate_password)
|
||||
charset='UTF8'
|
||||
sed -i "s/%password%/$dbpass/g" $RC_CONFIG_DIR/config.inc.php
|
||||
|
||||
if [ ! -z "$(echo "$DB_SYSTEM" | grep -w 'mysql')" ]; then
|
||||
add_mysql_database
|
||||
mysql_query "USE $database; $(< /var/lib/roundcube/SQL/mysql.initial.sql)"
|
||||
else
|
||||
add_pgsql_database
|
||||
psql_query "USE $database; $(< /var/lib/roundcube/SQL/postgres.initial.sql)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# TODO: Add support for PostgreSQL
|
||||
|
||||
rcDesKey="$(openssl rand -base64 30 | tr -d "/" | cut -c1-24)"
|
||||
sed -i "s/%des_key%/$rcDesKey/g" $RC_CONFIG_DIR/config.inc.php
|
||||
# Update server hostname in password change plugin
|
||||
sed -i "s/localhost/$(hostname)/g" $RC_CONFIG_DIR/plugins/password/config.inc.php
|
||||
|
||||
# Clean up
|
||||
rm -f -r $RC_INSTALL_DIR/installer
|
||||
rm -f -r $RC_INSTALL_DIR/$RC_FILE
|
||||
rm -f -r $RC_INSTALL_DIR/$RC_EXTRACT
|
||||
|
||||
# Updating hestia.conf
|
||||
if [ -z "$(grep WEBMAIL_SYSTEM $HESTIA/conf/hestia.conf)" ]; then
|
||||
$BIN/v-change-sys-config-value 'WEBMAIL_SYSTEM' 'roundcube'
|
||||
else
|
||||
if [ -z "$(echo "$WEBMAIL_SYSTEM" | grep -w 'roundcube')" ]; then
|
||||
if [ ! -z "$WEBMAIL_SYSTEM" ]; then
|
||||
$BIN/v-change-sys-config-value 'WEBMAIL_SYSTEM' "roundcube,$WEBMAIL_SYSTEM"
|
||||
else
|
||||
$BIN/v-change-sys-config-value 'WEBMAIL_SYSTEM' "roundcube"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
phpenmod mcrypt > /dev/null 2>&1
|
||||
else
|
||||
cd "$RC_INSTALL_DIR"
|
||||
[ ! -f "${RC_INSTALL_DIR}/${RC_FILE}" ] && wget "$RC_URL" --quiet -O "${RC_INSTALL_DIR}/${RC_FILE}"
|
||||
|
||||
tar xzf $RC_FILE
|
||||
|
||||
# Run Roundcube upgrade script
|
||||
$RC_INSTALL_DIR/$RC_EXTRACT/bin/installto.sh -y $RC_INSTALL_DIR > /dev/null 2>&1
|
||||
$RC_INSTALL_DIR/bin/update.sh --version "$version" > /dev/null 2>&1
|
||||
$RC_INSTALL_DIR/bin/indexcontacts.sh > /dev/null 2>&1
|
||||
chown -R root:$WWW_USER $RC_INSTALL_DIR
|
||||
|
||||
#clean up the mess
|
||||
if [ -d "$RC_INSTALL_DIR/installer" ]; then
|
||||
rm -f -r $RC_INSTALL_DIR/installer
|
||||
fi
|
||||
rm -f -r $RC_INSTALL_DIR/$RC_FILE
|
||||
rm -f -r $RC_INSTALL_DIR/$RC_EXTRACT
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ "$UPDATE" = "yes" ]; then
|
||||
$BIN/v-log-action "system" "Info" "Plugins" "Roundcube updated (Version: $version)."
|
||||
else
|
||||
$BIN/v-log-action "system" "Info" "Plugins" "Roundcube enabled (Version: $version)."
|
||||
fi
|
||||
log_event "$OK" "$ARGUMENTS"
|
@ -0,0 +1,99 @@
|
||||
#!/bin/bash
|
||||
# info: add system sftp jail
|
||||
# options: [RESTART]
|
||||
#
|
||||
# example: v-add-sys-sftp-jail yes
|
||||
#
|
||||
# This function enables sftp jailed environment.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
restart=$1
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Checking sshd directives
|
||||
config='/etc/ssh/sshd_config'
|
||||
sftp_n=$(grep -n "Subsystem.*sftp" $config | grep -v internal | grep -v ":#")
|
||||
sftp_i=$(grep -n "^# Hestia SFTP Chroot" $config)
|
||||
|
||||
# Disabling normal sftp
|
||||
if [ -n "$sftp_n" ]; then
|
||||
fline=$(echo $sftp_n | cut -f 1 -d :)
|
||||
sed -i "${fline}s/Subsystem.*sftp/#Subsystem sftp/" $config
|
||||
restart='yes'
|
||||
fi
|
||||
|
||||
# Enabling jailed sftp
|
||||
if [ -z "$sftp_i" ]; then
|
||||
echo " " >> $config
|
||||
echo "# Hestia SFTP Chroot" >> $config
|
||||
echo "Match User sftp_dummy99" >> $config
|
||||
echo "ChrootDirectory %h" >> $config
|
||||
echo " X11Forwarding no" >> $config
|
||||
echo " AllowTCPForwarding no" >> $config
|
||||
echo " ForceCommand internal-sftp" >> $config
|
||||
restart='yes'
|
||||
fi
|
||||
|
||||
# Validating opensshd config
|
||||
if [ "$restart" = 'yes' ]; then
|
||||
subj="OpenSSH restart failed"
|
||||
email=$(grep CONTACT $HESTIA/data/users/admin/user.conf | cut -f 2 -d \')
|
||||
/usr/sbin/sshd -t > /dev/null 2>&1
|
||||
if [ "$?" -ne 0 ]; then
|
||||
mail_text="OpenSSH can not be restarted. Please check config:
|
||||
\n\n$(/usr/sbin/sshd -t)"
|
||||
echo -e "$mail_text" | $SENDMAIL -s "$subj" $email
|
||||
else
|
||||
service ssh restart > /dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Checking users
|
||||
shells="rssh|nologin"
|
||||
for user in $(grep "$HOMEDIR" /etc/passwd | egrep "$shells" | cut -f 1 -d:); do
|
||||
# Include all users v-add-user-sftp-jail will handle it
|
||||
$BIN/v-add-user-sftp-jail "$user" "no"
|
||||
done
|
||||
|
||||
# Restart ssh service
|
||||
if [ "$restart" = 'no' ]; then
|
||||
# Skip restart of SSH daemon
|
||||
echo "" > /dev/null 2>&1
|
||||
else
|
||||
service ssh restart > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
# Add v-add-sys-sftp-jail to startup
|
||||
if [ ! -e "/etc/cron.d/hestia-sftp" ]; then
|
||||
echo "@reboot root sleep 60 && /usr/local/hestia/bin/v-add-sys-sftp-jail > /dev/null" > /etc/cron.d/hestia-sftp
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,63 @@
|
||||
#!/bin/bash
|
||||
# info: Add SMTP Account for logging, notification and internal mail
|
||||
# options: DOMAIN PORT SMTP_SECURITY USERNAME PASSWORD EMAIL
|
||||
#
|
||||
# example: v-add-sys-smtp example.com 587 STARTTLS test@domain.com securepassword test@example.com
|
||||
#
|
||||
# This function allows configuring a SMTP account for the server to use
|
||||
# for logging, notification and warn emails etc.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
domain=$1
|
||||
port=$2
|
||||
smtp_security=$3
|
||||
username=$4
|
||||
password=$5
|
||||
email=$6
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '6' "$#" 'DOMAIN PORT SMTP_SECURITY USERNAME PASSWORD EMAIL'
|
||||
is_format_valid 'domain' 'port' 'email' 'password'
|
||||
is_username_format_valid "$username" 'username'
|
||||
format_no_quotes "$password" 'passowrd'
|
||||
is_common_format_valid "$smtp_security" "SMTP_SECURITY"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
change_sys_value "USE_SERVER_SMTP" 'true'
|
||||
change_sys_value "SERVER_SMTP_HOST" "$domain"
|
||||
change_sys_value "SERVER_SMTP_PORT" "$port"
|
||||
change_sys_value "SERVER_SMTP_SECURITY" "$smtp_security"
|
||||
change_sys_value "SERVER_SMTP_USER" "$username"
|
||||
change_sys_value "SERVER_SMTP_PASSWD" "$password"
|
||||
change_sys_value "SERVER_SMTP_ADDR" "$email"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "Mail" "Server SMTP enabled."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,64 @@
|
||||
#!/bin/bash
|
||||
# info: add system wide smtp relay support
|
||||
# options: HOST [USERNAME] [PASSWORD] [PORT]
|
||||
#
|
||||
# example: v-add-sys-smtp-relay srv.smtprelay.tld uname123 pass12345
|
||||
#
|
||||
# This function adds system wide smtp relay support.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
host=$1
|
||||
username=$2
|
||||
password=$3
|
||||
port=${4-587}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'HOST [USERNAME] [PASSWORD] [PORT]'
|
||||
is_format_valid 'port' 'host' 'password'
|
||||
is_username_format_valid "$username" 'username'
|
||||
format_no_quotes "$password" 'passowrd'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
change_sys_value 'SMTP_RELAY' 'true'
|
||||
change_sys_value 'SMTP_RELAY_HOST' "$host"
|
||||
change_sys_value 'SMTP_RELAY_PORT' "$port"
|
||||
change_sys_value 'SMTP_RELAY_USER' "$username"
|
||||
|
||||
cat > /etc/exim4/smtp_relay.conf << EOL
|
||||
host:$host
|
||||
port:$port
|
||||
user:$username
|
||||
pass:$password
|
||||
EOL
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "Mail" "Server-wide SMTP Relay enabled (Host: $host, Port: $port)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,174 @@
|
||||
#!/bin/bash
|
||||
# info: Install SnappyMail webmail client
|
||||
# options: [MODE]
|
||||
#
|
||||
# This function installs the SnappyMail webmail client.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
# upgrade config file
|
||||
source "$HESTIA/install/upgrade/upgrade.conf"
|
||||
|
||||
MODE=$1
|
||||
UPDATE="no"
|
||||
# Version and Download paths
|
||||
# Version to be moved to upgrade script
|
||||
SM_FILE="snappymail-latest.tar.gz"
|
||||
# For removal of folder
|
||||
SM_EXTRACT_MAIN="snappymail"
|
||||
|
||||
# Downloading full version
|
||||
SM_URL="https://snappymail.eu/repository/latest.tar.gz"
|
||||
|
||||
# Folder paths
|
||||
SM_INSTALL_DIR="/var/lib/snappymail"
|
||||
SM_CONFIG_DIR="/etc/snappymail"
|
||||
SM_LOG="/var/log/snappymail"
|
||||
|
||||
WWW_USER="www-data"
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
WWW_USER="apache"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Checking root permissions
|
||||
if [ "x$(id -u)" != 'x0' ]; then
|
||||
echo "ERROR: v-add-sys-snappymail can only be executed by the root user"
|
||||
exit 10
|
||||
fi
|
||||
|
||||
# Ensure that $HESTIA (/usr/local/hestia/) and other variables are valid.
|
||||
if [ -z "$HESTIA" ]; then
|
||||
HESTIA="/usr/local/hestia"
|
||||
fi
|
||||
|
||||
if [ -z "$HOMEDIR" ] || [ -z "$HESTIA_INSTALL_DIR" ]; then
|
||||
echo "ERROR: Environment variables not present, installation aborted."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ -z "$(echo "$DB_SYSTEM" | grep -w 'mysql')" ]; then
|
||||
echo "ERROR: Mysql not available. Installation aborted"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Get current version
|
||||
if [ -f "/var/lib/snappymail/data/VERSION" ]; then
|
||||
version=$(cat $SM_INSTALL_DIR/data/VERSION)
|
||||
if [ "$version" == "$sm_v" ]; then
|
||||
echo "Error: Installed version ($version) is equal to the available version ($sm_v)"
|
||||
exit 2
|
||||
else
|
||||
UPDATE="yes"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ "$UPDATE" == "no" ]; then
|
||||
rm -f -r $SM_INSTALL_DIR
|
||||
rm -f -r $SM_CONFIG_DIR
|
||||
|
||||
mkdir $SM_INSTALL_DIR
|
||||
mkdir $SM_CONFIG_DIR
|
||||
|
||||
cd "$SM_INSTALL_DIR"
|
||||
[ ! -f "${SM_INSTALL_DIR}/${SM_FILE}" ] && wget "$SM_URL" --retry-connrefused --quiet -O "${SM_INSTALL_DIR}/${SM_FILE}"
|
||||
|
||||
if [ ! -f "${SM_INSTALL_DIR}/${SM_FILE}" ]; then
|
||||
echo "ERROR: Download failed, installation aborted."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Get current version
|
||||
|
||||
key=$(openssl rand -hex 4)
|
||||
|
||||
admin_account="admin_$key"
|
||||
admin_password=$(generate_password)
|
||||
|
||||
echo "Username: admin_$key" > ~/.snappymail
|
||||
echo "Password: $admin_password" >> ~/.snappymail
|
||||
echo "Secret key: admin_$key" >> ~/.snappymail
|
||||
|
||||
tar -xzf ${SM_INSTALL_DIR}/${SM_FILE}
|
||||
|
||||
mv ./data $SM_CONFIG_DIR/
|
||||
ln -s $SM_CONFIG_DIR/data/ ./data
|
||||
|
||||
if [ -f '/usr/bin/mariadb' ]; then
|
||||
mariadb -e "CREATE DATABASE snappymail" 2>&1
|
||||
r=$(generate_password)
|
||||
mariadb -e "GRANT ALL ON snappymail.*
|
||||
TO snappymail@localhost IDENTIFIED BY '$r'"
|
||||
else
|
||||
mysql -e "CREATE DATABASE snappymail" 2>&1
|
||||
r=$(generate_password)
|
||||
mysql -e "GRANT ALL ON snappymail.*
|
||||
TO snappymail@localhost IDENTIFIED BY '$r'"
|
||||
fi
|
||||
php -f $HESTIA_COMMON_DIR/snappymail/install.php "admin_$key" "$admin_password" "$r" "$BACKEND_PORT"
|
||||
|
||||
chown -R $WWW_USER:$WWW_USER ./data
|
||||
chown -R $WWW_USER:$WWW_USER $SM_CONFIG_DIR/
|
||||
|
||||
rm ${SM_INSTALL_DIR}/${SM_FILE}
|
||||
# Add robots.txt
|
||||
echo "User-agent: *" > $SM_INSTALL_DIR/robots.txt
|
||||
echo "Disallow: /" >> $SM_INSTALL_DIR/robots.txt
|
||||
|
||||
# Updating hestia.conf
|
||||
if [ -z "$(grep WEBMAIL_SYSTEM $HESTIA/conf/hestia.conf)" ]; then
|
||||
$BIN/v-change-sys-config-value 'WEBMAIL_SYSTEM' 'snappymail'
|
||||
else
|
||||
if [ -z "$(echo "$WEBMAIL_SYSTEM" | grep -w 'snappymail')" ]; then
|
||||
if [ -n "$WEBMAIL_SYSTEM" ]; then
|
||||
$BIN/v-change-sys-config-value 'WEBMAIL_SYSTEM' "snappymail,$WEBMAIL_SYSTEM"
|
||||
else
|
||||
$BIN/v-change-sys-config-value 'WEBMAIL_SYSTEM' "snappymail"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
else
|
||||
[ ! -f "${SM_INSTALL_DIR}/${SM_FILE}" ] && wget "$SM_URL" --quiet -O "${SM_INSTALL_DIR}/${SM_FILE}"
|
||||
version=$(cat $SM_INSTALL_DIR/data/VERSION)
|
||||
|
||||
tar -xzf snappymail-latest.tar.gz "data/VERSION" $SM_INSTALL_DIR/
|
||||
version_source=$(cat $SM_INSTALL_DIR/VERSION)
|
||||
|
||||
# Check version inside .tar.gz file in case hestia didn't update yet
|
||||
if [ "$version" != "$version_source" ]; then
|
||||
tar -xzf ${SM_INSTALL_DIR}/${SM_FILE}
|
||||
rm $SM_INSTALL_DIR/$SM_FILE
|
||||
fi
|
||||
rm ${SM_INSTALL_DIR}/VERSION
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ "$UPDATE" = "yes" ]; then
|
||||
$BIN/v-log-action "system" "Info" "Plugins" "SnappyMail updated (Version: $version)."
|
||||
else
|
||||
$BIN/v-log-action "system" "Info" "Plugins" "SnappyMail enabled (Version: $version)."
|
||||
fi
|
||||
log_event "$OK" "$ARGUMENTS"
|
@ -0,0 +1,286 @@
|
||||
#!/bin/bash
|
||||
# info: add system user
|
||||
# options: USER PASSWORD EMAIL [PACKAGE] [NAME] [LASTNAME]
|
||||
#
|
||||
# example: v-add-user admin2 P4$$w@rD bgates@aol.com
|
||||
#
|
||||
# This function creates new user account.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
password=$2
|
||||
HIDE=2
|
||||
email=$3
|
||||
package=${4-default}
|
||||
name=$5
|
||||
# Last name has been added for backward compatibility with WHMCS / Blesta VestaCP Plugins
|
||||
if [ -n "$6" ]; then
|
||||
name="$name $6"
|
||||
fi
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
is_user_free() {
|
||||
# these names may cause issues with MariaDB/MySQL database names and should be reserved:
|
||||
# sudo has been added due to Privilege escalation as sudo group has always sudo permission
|
||||
check_sysuser=$(php -r '$reserved_names=array("aria", "aria_log", "mysql", "mysql_upgrade", "ib", "ib_buffer",
|
||||
"ddl", "ddl_recovery", "performance", "sudo"); if(in_array(strtolower($argv[1]), $reserved_names, true)){echo implode(", ", $reserved_names);}' "$user")
|
||||
if [ -n "$check_sysuser" ]; then
|
||||
check_result "$E_INVALID" "The user name '$user' is reserved and cannot be used. List of reserved names: $check_sysuser"
|
||||
return
|
||||
fi
|
||||
check_sysuser=$(cut -f 1 -d : /etc/passwd | grep "^$user$")
|
||||
if [ -n "$check_sysuser" ] || [ -e "$USER_DATA" ]; then
|
||||
check_result "$E_EXISTS" "user $user exists"
|
||||
fi
|
||||
}
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER PASSWORD EMAIL [PACKAGE] [NAME] '
|
||||
is_format_valid 'user' 'email' 'package'
|
||||
if [ -n "$name" ]; then
|
||||
is_format_valid 'name'
|
||||
fi
|
||||
|
||||
is_user_free "$user"
|
||||
is_password_valid
|
||||
is_package_valid
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Parsing package data
|
||||
pkg_data=$(cat $HESTIA/data/packages/$package.pkg | egrep -v "TIME|DATE")
|
||||
|
||||
# Checking shell
|
||||
shell_conf=$(echo "$pkg_data" | grep 'SHELL' | cut -f 2 -d \')
|
||||
shell=$(grep -w "$shell_conf" /etc/shells | head -n1)
|
||||
|
||||
# Adding user
|
||||
/usr/sbin/useradd "$user" -s "$shell" -c "$email" -m -d "$HOMEDIR/$user" -U
|
||||
check_result $? "user creation failed" "$E_INVALID"
|
||||
|
||||
# Adding password
|
||||
echo "$user:$password" | /usr/sbin/chpasswd
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
# Delete user on failure
|
||||
/usr/sbin/deluser "$user" > /dev/null 2>&1
|
||||
echo "Error: Password not accepted due to PAM restrictions"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Add a general group for normal users created by Hestia
|
||||
if [ -z "$(grep ^hestia-users: /etc/group)" ]; then
|
||||
groupadd --system "hestia-users"
|
||||
fi
|
||||
|
||||
# Add membership to hestia-users group to non-admin users
|
||||
if [ "$user" = "admin" ]; then
|
||||
setfacl -m "g:admin:r-x" "$HOMEDIR/$user"
|
||||
else
|
||||
usermod -a -G "hestia-users" "$user"
|
||||
setfacl -m "u:$user:r-x" "$HOMEDIR/$user"
|
||||
fi
|
||||
setfacl -m "g:hestia-users:---" "$HOMEDIR/$user"
|
||||
|
||||
# Building directory tree
|
||||
mkdir $HOMEDIR/$user/conf
|
||||
|
||||
if [ -n "$WEB_SYSTEM" ]; then
|
||||
mkdir $HOMEDIR/$user/conf/web $HOMEDIR/$user/web $HOMEDIR/$user/tmp
|
||||
chmod 751 $HOMEDIR/$user/conf/web
|
||||
chmod 700 $HOMEDIR/$user/tmp
|
||||
chown $user:$user $HOMEDIR/$user/tmp
|
||||
chown root:$user $HOMEDIR/$user/web/
|
||||
fi
|
||||
|
||||
if [ -n "$MAIL_SYSTEM" ]; then
|
||||
mkdir $HOMEDIR/$user/conf/mail $HOMEDIR/$user/mail
|
||||
chmod 751 $HOMEDIR/$user/mail
|
||||
chmod 755 $HOMEDIR/$user/conf/mail
|
||||
fi
|
||||
|
||||
if [ -n "$DNS_SYSTEM" ]; then
|
||||
if [ "$DNS_SYSTEM" = 'named' ]; then
|
||||
dns_group='named'
|
||||
else
|
||||
dns_group='bind'
|
||||
fi
|
||||
mkdir $HOMEDIR/$user/conf/dns
|
||||
chmod 771 $HOMEDIR/$user/conf/dns
|
||||
chown root:$dns_group $HOMEDIR/$user/conf/dns
|
||||
fi
|
||||
|
||||
# Create default writeable folders
|
||||
mkdir $HOMEDIR/$user/.config \
|
||||
$HOMEDIR/$user/.cache \
|
||||
$HOMEDIR/$user/.local \
|
||||
$HOMEDIR/$user/.composer \
|
||||
$HOMEDIR/$user/.vscode-server \
|
||||
$HOMEDIR/$user/.ssh \
|
||||
$HOMEDIR/$user/.npm
|
||||
|
||||
chown $user:$user \
|
||||
$HOMEDIR/$user/.config \
|
||||
$HOMEDIR/$user/.cache \
|
||||
$HOMEDIR/$user/.local \
|
||||
$HOMEDIR/$user/.composer \
|
||||
$HOMEDIR/$user/.vscode-server \
|
||||
$HOMEDIR/$user/.ssh \
|
||||
$HOMEDIR/$user/.npm
|
||||
|
||||
# Set permissions
|
||||
chmod a+x $HOMEDIR/$user
|
||||
chattr +i $HOMEDIR/$user/conf > /dev/null 2>&1
|
||||
|
||||
# Adding user dir
|
||||
mkdir -p $USER_DATA/ssl $USER_DATA/dns $USER_DATA/mail
|
||||
|
||||
# Creating configuration files and pipes
|
||||
touch $USER_DATA/backup.conf \
|
||||
$USER_DATA/history.log \
|
||||
$USER_DATA/stats.log \
|
||||
$USER_DATA/web.conf \
|
||||
$USER_DATA/dns.conf \
|
||||
$USER_DATA/mail.conf \
|
||||
$USER_DATA/db.conf \
|
||||
$USER_DATA/cron.conf
|
||||
|
||||
chmod 770 $USER_DATA \
|
||||
$USER_DATA/ssl \
|
||||
$USER_DATA/dns \
|
||||
$USER_DATA/mail
|
||||
|
||||
chmod 660 $USER_DATA/backup.conf \
|
||||
$USER_DATA/history.log \
|
||||
$USER_DATA/stats.log \
|
||||
$USER_DATA/web.conf \
|
||||
$USER_DATA/dns.conf \
|
||||
$USER_DATA/mail.conf \
|
||||
$USER_DATA/db.conf \
|
||||
$USER_DATA/cron.conf
|
||||
|
||||
# Updating queue pipes
|
||||
echo "$BIN/v-update-user-disk $user" >> $HESTIA/data/queue/disk.pipe
|
||||
if [ -n "$WEB_SYSTEM" ]; then
|
||||
echo "$BIN/v-update-web-domains-traff $user" \
|
||||
>> $HESTIA/data/queue/traffic.pipe
|
||||
echo "$BIN/v-update-web-domains-disk $user" >> $HESTIA/data/queue/disk.pipe
|
||||
fi
|
||||
if [ -n "$MAIL_SYSTEM" ]; then
|
||||
echo "$BIN/v-update-mail-domains-disk $user" >> $HESTIA/data/queue/disk.pipe
|
||||
fi
|
||||
|
||||
if [ -n "$DB_SYSTEM" ]; then
|
||||
echo "$BIN/v-update-databases-disk $user" >> $HESTIA/data/queue/disk.pipe
|
||||
fi
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Filling user config
|
||||
if [ "$user" != 'admin' ]; then
|
||||
ip_avail=$($BIN/v-list-user-ips admin plain | grep -w shared | wc -l)
|
||||
u_users=0
|
||||
else
|
||||
ip_avail=0
|
||||
u_users=1
|
||||
fi
|
||||
|
||||
echo "NAME='$name'
|
||||
PACKAGE='$package'
|
||||
$pkg_data
|
||||
CONTACT='$email'
|
||||
CRON_REPORTS='yes'
|
||||
MD5='$(awk -v user=$user -F : 'user == $1 {print $2}' /etc/shadow)'
|
||||
RKEY='$(generate_password)'
|
||||
TWOFA=''
|
||||
QRCODE=''
|
||||
PHPCLI=''
|
||||
ROLE='user'
|
||||
SUSPENDED='no'
|
||||
SUSPENDED_USERS='0'
|
||||
SUSPENDED_WEB='0'
|
||||
SUSPENDED_DNS='0'
|
||||
SUSPENDED_MAIL='0'
|
||||
SUSPENDED_DB='0'
|
||||
SUSPENDED_CRON='0'
|
||||
IP_AVAIL='$ip_avail'
|
||||
IP_OWNED='0'
|
||||
U_USERS='$u_users'
|
||||
U_DISK='0'
|
||||
U_DISK_DIRS='0'
|
||||
U_DISK_WEB='0'
|
||||
U_DISK_MAIL='0'
|
||||
U_DISK_DB='0'
|
||||
U_BANDWIDTH='0'
|
||||
U_WEB_DOMAINS='0'
|
||||
U_WEB_SSL='0'
|
||||
U_WEB_ALIASES='0'
|
||||
U_DNS_DOMAINS='0'
|
||||
U_DNS_RECORDS='0'
|
||||
U_MAIL_DOMAINS='0'
|
||||
U_MAIL_DKIM='0'
|
||||
U_MAIL_ACCOUNTS='0'
|
||||
U_MAIL_SSL='0'
|
||||
U_DATABASES='0'
|
||||
U_CRON_JOBS='0'
|
||||
U_BACKUPS='0'
|
||||
LANGUAGE=''
|
||||
THEME=''
|
||||
NOTIFICATIONS='no'
|
||||
PREF_UI_SORT='name'
|
||||
LOGIN_DISABLED='no'
|
||||
LOGIN_USE_IPLIST='no'
|
||||
LOGIN_ALLOW_IPS=''
|
||||
TIME='$time'
|
||||
DATE='$date'" > $USER_DATA/user.conf
|
||||
chmod 660 $USER_DATA/user.conf
|
||||
|
||||
# Updating quota
|
||||
if [ "$DISK_QUOTA" = 'yes' ]; then
|
||||
$BIN/v-update-user-quota "$user"
|
||||
fi
|
||||
|
||||
# Updating admin counter
|
||||
if [ "$user" != 'admin' ]; then
|
||||
increase_user_value 'admin' '$U_USERS'
|
||||
fi
|
||||
|
||||
# Run template trigger
|
||||
if [ -x "$HESTIA/data/packages/$package.sh" ]; then
|
||||
$HESTIA/data/packages/$package.sh "$user" "$email" "$name"
|
||||
fi
|
||||
|
||||
# Adding jailed sftp env
|
||||
$BIN/v-add-user-sftp-jail $user
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "Users" "User account added (Name: $user)."
|
||||
$BIN/v-log-action "$user" "Info" "System" "Welcome!"
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,64 @@
|
||||
#!/bin/bash
|
||||
# info: add 2fa to existing user
|
||||
# options: USER
|
||||
#
|
||||
# example: v-add-user-2fa admin
|
||||
#
|
||||
# This function creates a new 2fa token for user.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'USER'
|
||||
is_format_valid 'user' 'system'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Reading user values
|
||||
source $USER_DATA/user.conf
|
||||
|
||||
# Check if 2FA is already enabled
|
||||
if [ -n "$TWOFA" ]; then
|
||||
echo "Error: 2FA already enabled"
|
||||
exit "$E_EXISTS"
|
||||
fi
|
||||
|
||||
# Get secret and qr code from 2fa library
|
||||
data=$($HESTIA_PHP $HESTIA/web/inc/2fa/secret.php)
|
||||
|
||||
# Split to secret and qrcode using delimiter
|
||||
IFS='-' read -r -a array <<< "$data"
|
||||
secret=${array[0]}
|
||||
qrcode=${array[1]}
|
||||
|
||||
# Save the secret in user config (needs encryption?)
|
||||
update_user_value "$user" '$TWOFA' "$secret"
|
||||
update_user_value "$user" '$QRCODE' "$qrcode"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
exit
|
@ -0,0 +1,95 @@
|
||||
#!/bin/bash
|
||||
# info: add composer (php dependency manager) for a user
|
||||
# options: USER
|
||||
#
|
||||
# example: v-add-user-composer user [version]
|
||||
#
|
||||
# This function adds support for composer (php dependency manager)
|
||||
# Homepage: <https://getcomposer.org/>
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
version=${2-2}
|
||||
|
||||
if [ -z "$HESTIA" ]; then
|
||||
HESTIA="/usr/local/hestia"
|
||||
fi
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'USER [VERSION]'
|
||||
is_format_valid 'user'
|
||||
is_number_format_valid "$version" "version"
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
|
||||
[ -z "$HOMEDIR" ] && check_result "$E_NOTEXIST" "Hestia environment vars not present"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
COMPOSER_DIR="$HOMEDIR/$user/.composer"
|
||||
COMPOSER_BIN="$COMPOSER_DIR/composer"
|
||||
|
||||
if [ -f "$COMPOSER_BIN" ]; then
|
||||
echo "Composer already available"
|
||||
exit
|
||||
fi
|
||||
|
||||
[ -z "$(readlink -m "$COMPOSER_DIR" | egrep "^$HOMEDIR/$user/")" ] && check_result "$E_FORBIDEN" "Path outside of user homedir (Composer dir)"
|
||||
[ -z "$(readlink -m "$COMPOSER_BIN" | egrep "^$HOMEDIR/$user/")" ] && check_result "$E_FORBIDEN" "Path outside of user homedir (Composer bin)"
|
||||
[ -z "$(readlink -m "$HOMEDIR/$user/.config/" | egrep "^$HOMEDIR/$user/")" ] && check_result "$E_FORBIDEN" "Path outside of user homedir (.conf)"
|
||||
|
||||
mkdir -p "$COMPOSER_DIR"
|
||||
chown $user: "$COMPOSER_DIR"
|
||||
mkdir -p "$HOMEDIR/$user/.config"
|
||||
chown $user: "$HOMEDIR/$user/.config"
|
||||
echo "alias composer=/home/"$user"/.composer/composer" >> /home/$user/.bash_aliases
|
||||
|
||||
COMPOSER_SETUP_FILE=$(mktemp)
|
||||
check_result $? "Create temp file"
|
||||
chown $user: "$COMPOSER_SETUP_FILE"
|
||||
|
||||
signature="$(curl --silent --show-error https://composer.github.io/installer.sig)"
|
||||
check_result $? "Download signature"
|
||||
|
||||
user_exec wget --tries=3 --timeout=15 --read-timeout=15 --waitretry=3 --no-dns-cache https://getcomposer.org/installer --quiet -O "$COMPOSER_SETUP_FILE"
|
||||
check_result $? "Download composer installer"
|
||||
|
||||
if [[ "$signature" != $(sha384sum "$COMPOSER_SETUP_FILE" | cut -f 1 -d " ") ]]; then
|
||||
rm -f "$COMPOSER_SETUP_FILE"
|
||||
check_result "$E_INVALID" "Composer signature does not match"
|
||||
fi
|
||||
|
||||
COMPOSER_HOME="$HOMEDIR/$user/.config/composer" user_exec /usr/bin/php "$COMPOSER_SETUP_FILE" --quiet "--$version" --install-dir="$COMPOSER_DIR" --filename=composer
|
||||
check_result $? "Composer install failed"
|
||||
|
||||
[ -f "$COMPOSER_SETUP_FILE" ] && rm -f "$COMPOSER_SETUP_FILE"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Plugins" "Composer support enabled."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,79 @@
|
||||
#!/bin/bash
|
||||
# info: add user notification
|
||||
# options: USER TOPIC NOTICE [TYPE]
|
||||
#
|
||||
# This function adds a new user notification to the panel.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
topic=$(echo $2 | sed "s/'/%quote%/g")
|
||||
notice=$(echo $3 | sed "s/'/%quote%/g")
|
||||
type=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER TOPIC NOTICE [TYPE]'
|
||||
is_format_valid 'user' 'topic' 'notice'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Defining notification id
|
||||
if [ -e "$USER_DATA/notifications.conf" ]; then
|
||||
nid=$(grep "NID=" $USER_DATA/notifications.conf | cut -f 2 -d \')
|
||||
nid=$(echo "$nid" | sort -n | tail -n1)
|
||||
if [ -n "$nid" ]; then
|
||||
nid="$((nid + 1))"
|
||||
else
|
||||
nid=1
|
||||
fi
|
||||
else
|
||||
nid=1
|
||||
fi
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Concatenating string
|
||||
str="NID='$nid' TOPIC='$topic' NOTICE='$notice' TYPE='$type'"
|
||||
str="$str ACK='no' TIME='$time' DATE='$date'"
|
||||
|
||||
# Adding to config
|
||||
echo "$str" >> $USER_DATA/notifications.conf
|
||||
|
||||
# Changing permissions
|
||||
chmod 660 $USER_DATA/notifications.conf
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Updating notification counter
|
||||
if [ -z "$(grep NOTIFICATIONS $USER_DATA/user.conf)" ]; then
|
||||
sed -i "s/^TIME/NOTIFICATIONS='yes'\nTIME/g" $USER_DATA/user.conf
|
||||
else
|
||||
update_user_value "$user" '$NOTIFICATIONS' "yes"
|
||||
fi
|
||||
|
||||
exit
|
@ -0,0 +1,154 @@
|
||||
#!/bin/bash
|
||||
# info: adding user package
|
||||
# options: tmpfile PACKAGE [REWRITE]
|
||||
#
|
||||
# This function adds new user package to the system.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
tmpfile=$1
|
||||
package=$2
|
||||
rewrite=$3
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
is_package_consistent() {
|
||||
source_conf "$tmpfile"
|
||||
if [ "$WEB_DOMAINS" != 'unlimited' ]; then
|
||||
is_int_format_valid "$WEB_DOMAINS" 'WEB_DOMAINS'
|
||||
fi
|
||||
if [ "$WEB_ALIASES" != 'unlimited' ]; then
|
||||
is_int_format_valid "$WEB_ALIASES" 'WEB_ALIASES'
|
||||
fi
|
||||
if [ "$DNS_DOMAINS" != 'unlimited' ]; then
|
||||
is_int_format_valid "$DNS_DOMAINS" 'DNS_DOMAINS'
|
||||
fi
|
||||
if [ "$DNS_RECORDS" != 'unlimited' ]; then
|
||||
is_int_format_valid "$DNS_RECORDS" 'DNS_RECORDS'
|
||||
fi
|
||||
if [ "$MAIL_DOMAINS" != 'unlimited' ]; then
|
||||
is_int_format_valid "$MAIL_DOMAINS" 'MAIL_DOMAINS'
|
||||
fi
|
||||
if [ "$MAIL_ACCOUNTS" != 'unlimited' ]; then
|
||||
is_int_format_valid "$MAIL_ACCOUNTS" 'MAIL_ACCOUNTS'
|
||||
fi
|
||||
if [ "$DATABASES" != 'unlimited' ]; then
|
||||
is_int_format_valid "$DATABASES" 'DATABASES'
|
||||
fi
|
||||
if [ "$CRON_JOBS" != 'unlimited' ]; then
|
||||
is_int_format_valid "$CRON_JOBS" 'CRON_JOBS'
|
||||
fi
|
||||
|
||||
is_int_format_valid "$RATE_LIMIT" 'RATE_LIMIT'
|
||||
|
||||
if [ "$DISK_QUOTA" != 'unlimited' ]; then
|
||||
is_int_format_valid "$DISK_QUOTA" 'DISK_QUOTA'
|
||||
fi
|
||||
if [ "$BANDWIDTH" != 'unlimited' ]; then
|
||||
is_int_format_valid "$BANDWIDTH" 'BANDWIDTH'
|
||||
fi
|
||||
is_int_format_valid "$BACKUPS" 'BACKUPS'
|
||||
if [ -n "$WEB_TEMPLATE" ]; then
|
||||
is_web_template_valid "$WEB_TEMPLATE"
|
||||
fi
|
||||
if [ -n "$BACKEND_TEMPLATE" ]; then
|
||||
is_backend_template_valid "$BACKEND_TEMPLATE"
|
||||
fi
|
||||
if [ -n "$PROXY_TEMPLATE" ]; then
|
||||
is_proxy_template_valid "$PROXY_TEMPLATE"
|
||||
fi
|
||||
if [ -n "$DNS_TEMPLATE" ]; then
|
||||
is_dns_template_valid "$DNS_TEMPLATE"
|
||||
fi
|
||||
if [ -n "$NS" ]; then
|
||||
IFS=',' read -r -a nameservers <<< "$NS"
|
||||
i=1
|
||||
for ns in "${nameservers[@]}"; do
|
||||
is_domain_format_valid "$ns" "ns$i"
|
||||
i=$((i + 1))
|
||||
done
|
||||
fi
|
||||
|
||||
is_format_valid_shell "$SHELL"
|
||||
}
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'PKG_DIR PACKAGE' 'rewrite'
|
||||
is_format_valid 'package'
|
||||
if [ "$rewrite" != 'yes' ]; then
|
||||
is_package_new "$package"
|
||||
else
|
||||
is_package_valid "$package"
|
||||
fi
|
||||
|
||||
if [ ! -f "$tmpfile" ]; then
|
||||
echo "$tmpfile does not exists"
|
||||
exit "$E_NOTEXIST"
|
||||
fi
|
||||
|
||||
is_package_consistent
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
SHELL=$(basename $SHELL)
|
||||
echo "WEB_TEMPLATE='$WEB_TEMPLATE'
|
||||
PROXY_TEMPLATE='$PROXY_TEMPLATE'
|
||||
BACKEND_TEMPLATE='$BACKEND_TEMPLATE'
|
||||
DNS_TEMPLATE='$DNS_TEMPLATE'
|
||||
WEB_DOMAINS='$WEB_DOMAINS'
|
||||
WEB_ALIASES='$WEB_ALIASES'
|
||||
DNS_DOMAINS='$DNS_DOMAINS'
|
||||
DNS_RECORDS='$DNS_RECORDS'
|
||||
MAIL_DOMAINS='$MAIL_DOMAINS'
|
||||
MAIL_ACCOUNTS='$MAIL_ACCOUNTS'
|
||||
RATE_LIMIT='$RATE_LIMIT'
|
||||
DATABASES='$DATABASES'
|
||||
CRON_JOBS='$CRON_JOBS'
|
||||
DISK_QUOTA='$DISK_QUOTA'
|
||||
BANDWIDTH='$BANDWIDTH'
|
||||
NS='$NS'
|
||||
SHELL='$SHELL'
|
||||
BACKUPS='$BACKUPS'
|
||||
TIME='$time'
|
||||
DATE='$date'
|
||||
" > "$HESTIA/data/packages/$package.pkg"
|
||||
|
||||
chmod 644 "$HESTIA/data/packages/$package.pkg"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
if [ "$rewrite" != 'yes' ]; then
|
||||
$BIN/v-log-action "system" "Info" "Packages" "Package added (Name: $package)."
|
||||
else
|
||||
$BIN/v-log-action "system" "Info" "Packages" "Package limits updated (Name: $package)."
|
||||
fi
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,94 @@
|
||||
#!/bin/bash
|
||||
# info: add user sftp jail
|
||||
# options: USER [RESTART]
|
||||
#
|
||||
# example: v-add-user-sftp-jail admin
|
||||
#
|
||||
# This function enables sftp jailed environment
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
restart=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'USER'
|
||||
is_format_valid 'user'
|
||||
check=$(is_object_valid 'user' 'USER' "$user")
|
||||
if [ $? -ne 0 ]; then
|
||||
user_str=$(grep "^$user:" /etc/passwd | egrep "rssh|nologin")
|
||||
#try to detect "owner" of the ftp_user if not found dont set it up
|
||||
user_owner=$(echo $user_str | cut -f6 -d : | cut -f3 -d /)
|
||||
is_object_valid 'user' 'USER' "$user_owner"
|
||||
fi
|
||||
user_str=$(grep "^$user:" /etc/passwd | egrep "rssh|nologin")
|
||||
if [ -z "$user_str" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Get current users and split into array
|
||||
ssh_users=$(grep -A1 "^# Hestia SFTP Chroot" /etc/ssh/sshd_config | sed -n 2p | sed 's/Match User //')
|
||||
IFS=',' read -r -a users <<< "$ssh_users"
|
||||
|
||||
# Check if jail exist
|
||||
match_string="$ssh_users,"
|
||||
if [[ "$match_string" =~ ,$user, ]]; then
|
||||
if [[ -d /home/$user && -z "$(find /home/$user -user root -print -prune -o -prune)" ]]; then
|
||||
chown root:root /home/$user
|
||||
fi
|
||||
exit
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Add user to array
|
||||
users+=($user)
|
||||
|
||||
# Write new user list to config
|
||||
users=$(
|
||||
IFS=','
|
||||
echo "${users[*]// /|}"
|
||||
IFS=$' \t\n'
|
||||
)
|
||||
sed -i "s/$ssh_users/$users/g" /etc/ssh/sshd_config
|
||||
|
||||
# Set home folder permission to root
|
||||
if [ -d "/home/$user" ]; then
|
||||
chown root:root /home/$user
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Restart ssh service
|
||||
if [ "$restart" = 'no' ]; then
|
||||
# Skip restart of SSH daemon
|
||||
echo "" > /dev/null 2>&1
|
||||
else
|
||||
service ssh restart > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,82 @@
|
||||
#!/bin/bash
|
||||
# info: add user sftp key
|
||||
# options: USER [TTL]
|
||||
#
|
||||
# This function creates and updates SSH keys for used with the File Manager.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
ttl=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'USER [TTL]'
|
||||
is_format_valid 'user' 'ttl'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
PRVKEY_FILE="$HOMEDIR/$user/.ssh/hst-filemanager-key"
|
||||
PUBKEY_FILE="$HOMEDIR/$user/.ssh/hst-filemanager-key.pub"
|
||||
AUTHKEY_FILE="$HOMEDIR/$user/.ssh/authorized_keys"
|
||||
|
||||
[ -z "$(readlink -f "$PRVKEY_FILE" | egrep "^$HOMEDIR/$user/.ssh/")" ] && check_result "$E_FORBIDEN" "Invalid private key file path"
|
||||
[ -z "$(readlink -f "$PUBKEY_FILE" | egrep "^$HOMEDIR/$user/.ssh/")" ] && check_result "$E_FORBIDEN" "Invalid public key file path"
|
||||
[ -z "$(readlink -f "$AUTHKEY_FILE" | egrep "^$HOMEDIR/$user/.ssh/")" ] && check_result "$E_FORBIDEN" "Invalid authorized keys path"
|
||||
|
||||
if [ ! -f "${PRVKEY_FILE}" ]; then
|
||||
ssh-keygen -q -b 1024 -t rsa -f "${PRVKEY_FILE}" -N ""
|
||||
rm "${PUBKEY_FILE}"
|
||||
new_privkey=true
|
||||
fi
|
||||
|
||||
if [ ! -f "${AUTHKEY_FILE}" ] || [ "$new_privkey" = true ]; then
|
||||
pubkey_str="$(ssh-keygen -y -f ${PRVKEY_FILE})"
|
||||
pubkey_desc="filemanager.ssh.key"
|
||||
|
||||
if grep --quiet --no-messages -F "$pubkey_desc" "${AUTHKEY_FILE}"; then
|
||||
sed -i "/filemanager\.ssh\.key\$/d" "${AUTHKEY_FILE}"
|
||||
fi
|
||||
|
||||
# make sure authorized_keys is ending with EOL
|
||||
[ -f "${AUTHKEY_FILE}" ] && sed -i '$a\' "${AUTHKEY_FILE}"
|
||||
|
||||
expire=0
|
||||
if [[ "$ttl" -gt 0 ]]; then
|
||||
expire=$(date +%s -d "+${ttl} min")
|
||||
echo "rm ${PRVKEY_FILE}" | at "now +${ttl} minute" > /dev/null 2>&1
|
||||
fi
|
||||
echo "from=\"127.0.0.1\",command=\"internal-sftp\",restrict ${pubkey_str} TS:${expire} ${pubkey_desc}" >> "${AUTHKEY_FILE}"
|
||||
fi
|
||||
|
||||
#
|
||||
chown ${user}: "${AUTHKEY_FILE}"
|
||||
chown admin: "${PRVKEY_FILE}"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,73 @@
|
||||
#!/bin/bash
|
||||
# info: add ssh key
|
||||
# options: USER KEY
|
||||
#
|
||||
# example: v-add-user-ssh-key user 'valid ssh key'
|
||||
#
|
||||
# Function check if $user/.ssh/authorized_keys exists and create it.
|
||||
# After that it append the new key(s)
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
key=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER SSH_PUBLIC_KEY'
|
||||
is_format_valid 'user'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Reading user values
|
||||
source $USER_DATA/user.conf
|
||||
|
||||
AUTHKEY_FILE="$HOMEDIR/$user/.ssh/authorized_keys"
|
||||
[ -z "$(readlink -f "$AUTHKEY_FILE" | egrep "^$HOMEDIR/$user/.ssh/")" ] && check_result "$E_FORBIDEN" "Invalid authorized keys path"
|
||||
|
||||
# Check if file exits
|
||||
if [ ! -f "$AUTHKEY_FILE" ]; then
|
||||
v-add-fs-file "$user" "${AUTHKEY_FILE}"
|
||||
fi
|
||||
|
||||
[ -z "$key" ] && check_result "$E_NOTEXIST" "Empty ssh public key"
|
||||
|
||||
if ! echo "$key" | ssh-keygen -l -f - > /dev/null 2>&1; then
|
||||
check_result "$E_PARSING" "Validating user private key"
|
||||
fi
|
||||
|
||||
# Make sure authorized_keys ends with EOL
|
||||
[ -f "${AUTHKEY_FILE}" ] && sed -i '$a\' "${AUTHKEY_FILE}"
|
||||
|
||||
# Append key data to file
|
||||
echo "$key" >> "$AUTHKEY_FILE"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "System" "Added a new SSH key."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,69 @@
|
||||
#!/bin/bash
|
||||
# info: add wp-cli for a user
|
||||
# options: USER
|
||||
#
|
||||
# example: v-add-user-wp-cli user
|
||||
#
|
||||
# This function adds support for wp-cli to the user account
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
|
||||
if [ -z "$HESTIA" ]; then
|
||||
HESTIA="/usr/local/hestia"
|
||||
fi
|
||||
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'USER'
|
||||
is_format_valid 'user'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
WPCLI_DIR="/home/$user/.wp-cli"
|
||||
WPCLI_BIN="$WPCLI_DIR/wp"
|
||||
|
||||
if [ -f "$WPCLI_BIN" ]; then
|
||||
check_result "$E_EXISTS" "For user name '$user' WP-CLI already available!"
|
||||
exit
|
||||
fi
|
||||
|
||||
[ -z "$(readlink -m "$WPCLI_DIR" | egrep "^$HOMEDIR/$user/")" ] && check_result "$E_FORBIDEN" "Path outside of user homedir (WP Cli dir)"
|
||||
[ -z "$(readlink -m "$WPCLI_BIN" | egrep "^$HOMEDIR/$user/")" ] && check_result "$E_FORBIDEN" "Path outside of user homedir (WP Cli bin)"
|
||||
|
||||
mkdir -p "$WPCLI_DIR"
|
||||
chown $user:$user "$WPCLI_DIR"
|
||||
|
||||
user_exec wget --tries=3 --timeout=15 --read-timeout=15 --waitretry=3 --no-dns-cache --quiet -O "$WPCLI_BIN" https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
|
||||
user_exec chmod +x "$WPCLI_BIN"
|
||||
user_exec echo -e "#add wp-cli alias for user\nalias wp='php $WPCLI_BIN'" >> ~/.bashrc
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Plugins" "WP-CLI support enabled."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,257 @@
|
||||
#!/bin/bash
|
||||
# info: add web domain
|
||||
# options: USER DOMAIN [IP] [RESTART] [ALIASES] [PROXY_EXTENSIONS]
|
||||
#
|
||||
# example: v-add-web-domain admin wonderland.com 192.18.22.43 yes www.wonderland.com
|
||||
#
|
||||
# This function adds virtual host to a server. In cases when ip is
|
||||
# undefined in the script, "default" template will be used. The alias of
|
||||
# www.domain.tld type will be automatically assigned to the domain unless
|
||||
# "none" is transmited as argument. If ip have associated dns name, this
|
||||
# domain will also get the alias domain-tpl.$ipname. An alias with the ip
|
||||
# name is useful during the site testing while dns isn't moved to server yet.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
ip=$3
|
||||
restart=$4 # will be moved to the end soon
|
||||
aliases=$5
|
||||
proxy_ext=$6
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# shellcheck source=/usr/local/hestia/func/syshealth.sh
|
||||
source $HESTIA/func/syshealth.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
format_aliases
|
||||
domain_utf=$(idn2 --quiet -d "$domain_idn")
|
||||
|
||||
|
||||
WWW_USER="www-data"
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
WWW_USER="apache"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
|
||||
check_args '2' "$#" 'USER DOMAIN [IP] [RESTART] [ALIASES] [PROXY_EXTENSIONS]'
|
||||
is_format_valid 'user' 'domain' 'aliases' 'ip' 'proxy_ext'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_package_full 'WEB_DOMAINS'
|
||||
|
||||
if [ "$aliases" != "none" ]; then
|
||||
ALIAS="$aliases"
|
||||
is_package_full 'WEB_ALIASES'
|
||||
fi
|
||||
|
||||
if [ "$($BIN/v-list-web-domain $user $domain_utf plain | cut -f 1) " != "$domain" ]; then
|
||||
is_domain_new 'web' "$domain_utf,$aliases"
|
||||
fi
|
||||
if [ "$($BIN/v-list-web-domain $user $domain_idn plain | cut -f 1) " != "$domain" ]; then
|
||||
is_domain_new 'web' "$domain_idn,$aliases"
|
||||
else
|
||||
is_domain_new 'web' "$domain,$aliases"
|
||||
fi
|
||||
if [ -z "$(is_ip_format_valid $domain)" ]; then
|
||||
echo "Error: Invalid domain format. IP address detected as input."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
is_dir_symlink "$HOMEDIR/$user/web"
|
||||
is_dir_symlink "$HOMEDIR/$user/web/$domain"
|
||||
|
||||
is_base_domain_owner "$domain,$aliases"
|
||||
|
||||
if [ -n "$ip" ]; then
|
||||
is_ip_valid "$ip" "$user"
|
||||
else
|
||||
get_user_ip
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Reading user values
|
||||
source_conf "$USER_DATA/user.conf"
|
||||
|
||||
[[ -e "$HOMEDIR/$user/web/$domain" ]] && check_result "$E_EXISTS" "Web domain folder for $domain should not exist"
|
||||
|
||||
# Creating domain directories
|
||||
mkdir $HOMEDIR/$user/web/$domain
|
||||
chown $user:$user $HOMEDIR/$user/web/$domain
|
||||
$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/public_html"
|
||||
$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/document_errors"
|
||||
$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/cgi-bin"
|
||||
$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/private"
|
||||
$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/stats"
|
||||
$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/logs"
|
||||
|
||||
# Creating domain logs
|
||||
touch /var/log/$WEB_SYSTEM/domains/$domain.bytes \
|
||||
/var/log/$WEB_SYSTEM/domains/$domain.log \
|
||||
/var/log/$WEB_SYSTEM/domains/$domain.error.log
|
||||
ln -f -s /var/log/$WEB_SYSTEM/domains/$domain.*log \
|
||||
$HOMEDIR/$user/web/$domain/logs/
|
||||
|
||||
# Adding domain skeleton
|
||||
user_exec cp -r $WEBTPL/skel/* "$HOMEDIR/$user/web/$domain/" > /dev/null 2>&1
|
||||
for file in $(find "$HOMEDIR/$user/web/$domain/" -type f); do
|
||||
sed -i "s/%domain%/$domain/g" $file
|
||||
done
|
||||
|
||||
# Changing file owner & permission
|
||||
chown -R $user:$user $HOMEDIR/$user/web/$domain
|
||||
chown root:$user /var/log/$WEB_SYSTEM/domains/$domain.* $conf
|
||||
chmod 640 /var/log/$WEB_SYSTEM/domains/$domain.*
|
||||
user_exec chmod 751 $HOMEDIR/$user/web/$domain/*
|
||||
user_exec chmod 551 $HOMEDIR/$user/web/$domain/stats $HOMEDIR/$user/web/$domain/logs
|
||||
user_exec chmod 644 $HOMEDIR/$user/web/$domain/public_*html/*
|
||||
user_exec chmod 551 $HOMEDIR/$user/web/$domain
|
||||
chown --no-dereference $user:$WWW_USER $HOMEDIR/$user/web/$domain/public_*html
|
||||
|
||||
# Adding PHP-FPM backend
|
||||
if [ -n "$WEB_BACKEND" ]; then
|
||||
if [ -z "$BACKEND_TEMPLATE" ]; then
|
||||
BACKEND_TEMPLATE='default'
|
||||
if [ -z "$(grep BACKEND_TEMPLATE $USER_DATA/user.conf)" ]; then
|
||||
sed -i "s/^DNS_TEMPL/BACKEND_TEMPLATE='default'\nDNS_TEMPL/g" \
|
||||
$USER_DATA/user.conf
|
||||
else
|
||||
update_user_value "$user" '$BACKEND_TEMPLATE' "default"
|
||||
fi
|
||||
fi
|
||||
export BACKEND="$BACKEND_TEMPLATE"
|
||||
$BIN/v-add-web-domain-backend "$user" "$domain" "$BACKEND_TEMPLATE" "$restart"
|
||||
check_result $? "Backend error" > /dev/null
|
||||
fi
|
||||
|
||||
# Preparing domain aliases
|
||||
if [ "$aliases" = 'none' ]; then
|
||||
ALIAS=''
|
||||
else
|
||||
ALIAS="www.$domain"
|
||||
if [ -z "$aliases" ]; then
|
||||
# Check and skip www alias for subdomains.
|
||||
IFS='.' read -r -a domain_elements <<< "$domain"
|
||||
if [ "${#domain_elements[@]}" -gt 2 ]; then
|
||||
is_valid_2_part_extension $domain
|
||||
if [ $? -ne 0 ]; then
|
||||
ALIAS=""
|
||||
else
|
||||
ALIAS="www.$domain"
|
||||
fi
|
||||
else
|
||||
ALIAS="www.$domain"
|
||||
fi
|
||||
else
|
||||
ALIAS="$aliases"
|
||||
fi
|
||||
|
||||
ip_alias=$(get_ip_alias "$domain")
|
||||
if [ -n "$ip_alias" ]; then
|
||||
ALIAS="$ALIAS,$ip_alias"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Preparing domain variables
|
||||
prepare_web_domain_values
|
||||
|
||||
if [ -z "$WEB_TEMPLATE" ]; then
|
||||
WEB_TEMPLATE='default'
|
||||
update_user_value "$user" '$WEB_TEMPLATE' "default"
|
||||
fi
|
||||
|
||||
# Adding web server config
|
||||
add_web_config "$WEB_SYSTEM" "$WEB_TEMPLATE.tpl"
|
||||
|
||||
# Adding proxy config
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
PROXY_EXT="$proxy_ext"
|
||||
if [ -z "$proxy_ext" ]; then
|
||||
# Code
|
||||
PROXY_EXT="css,htm,html,js,json,xml"
|
||||
# Image (from https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types)
|
||||
PROXY_EXT="$PROXY_EXT,apng,avif,bmp,cur,gif,ico,jfif,jpg,jpeg,pjp,pjpeg,png,svg,tif,tiff,webp"
|
||||
# Audio from (https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Audio_codecs)
|
||||
PROXY_EXT="$PROXY_EXT,aac,caf,flac,m4a,midi,mp3,ogg,opus,wav"
|
||||
# Video (from https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Video_codecs)
|
||||
PROXY_EXT="$PROXY_EXT,3gp,av1,avi,m4v,mkv,mov,mpg,mpeg,mp4,mp4v,webm"
|
||||
# Fonts
|
||||
PROXY_EXT="$PROXY_EXT,otf,ttf,woff,woff2"
|
||||
# Productivity
|
||||
PROXY_EXT="$PROXY_EXT,doc,docx,odf,odp,ods,odt,pdf,ppt,pptx,rtf,txt,xls,xlsx"
|
||||
# Archive
|
||||
PROXY_EXT="$PROXY_EXT,7z,bz2,gz,rar,tar,tgz,zip"
|
||||
# Binaries
|
||||
PROXY_EXT="$PROXY_EXT,apk,appx,bin,dmg,exe,img,iso,jar,msi"
|
||||
fi
|
||||
if [ -z "$PROXY_TEMPLATE" ]; then
|
||||
PROXY_TEMPLATE='default'
|
||||
update_user_value "$user" '$PROXY_TEMPLATE' "default"
|
||||
fi
|
||||
|
||||
add_web_config "$PROXY_SYSTEM" "$PROXY_TEMPLATE.tpl"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Increasing counters
|
||||
increase_ip_value "$local_ip"
|
||||
increase_user_value "$user" '$U_WEB_DOMAINS'
|
||||
increase_user_value "$user" '$U_WEB_ALIASES' "$alias_number"
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Adding domain in web.conf
|
||||
echo "DOMAIN='$domain' IP='$ip' IP6='' CUSTOM_DOCROOT='' ALIAS='$ALIAS' TPL='$WEB_TEMPLATE'\
|
||||
SSL='no' SSL_FORCE='no' SSL_HOME='same' LETSENCRYPT='no' FTP_USER='' FTP_MD5=''\
|
||||
BACKEND='$BACKEND_TEMPLATE' PROXY='$PROXY_TEMPLATE' PROXY_EXT='$PROXY_EXT'\
|
||||
STATS='' STATS_USER='' STATS_CRYPT='' U_DISK='0' U_BANDWIDTH='0'\
|
||||
SUSPENDED='no' TIME='$time' DATE='$date'" >> $USER_DATA/web.conf
|
||||
|
||||
syshealth_repair_web_config
|
||||
|
||||
# Restarting web server
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
|
||||
# Restarting proxy server
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Added new web domain (Name: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,114 @@
|
||||
#!/bin/bash
|
||||
# info: add web domain alias
|
||||
# options: USER DOMAIN ALIASES [RESTART]
|
||||
#
|
||||
# example: v-add-web-domain-alias admin acme.com www.acme.com yes
|
||||
#
|
||||
# This function adds one or more aliases to a domain (it is also called
|
||||
# "domain parking"). This function supports wildcards *.domain.tpl.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
aliases=$3
|
||||
restart="$4"
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
format_aliases
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ -z "$aliases" ]; then
|
||||
check_result "$E_INVALID" "Invalid alias format: empty"
|
||||
fi
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN ALIASES [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'aliases'
|
||||
is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
is_domain_new 'web' "$aliases"
|
||||
is_base_domain_owner "$aliases"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
get_domain_values 'web'
|
||||
|
||||
# Preparing domain values for the template substitution
|
||||
local_ip=$(get_real_ip $IP)
|
||||
if [ -z "$ALIAS" ]; then
|
||||
ALIAS="$aliases"
|
||||
else
|
||||
ALIAS="$ALIAS,$aliases"
|
||||
fi
|
||||
prepare_web_domain_values
|
||||
|
||||
is_package_full 'WEB_ALIASES'
|
||||
|
||||
# Rebuilding vhost
|
||||
del_web_config "$WEB_SYSTEM" "$TPL.tpl"
|
||||
add_web_config "$WEB_SYSTEM" "$TPL.tpl"
|
||||
if [ "$SSL" = 'yes' ]; then
|
||||
del_web_config "$WEB_SYSTEM" "$TPL.stpl"
|
||||
add_web_config "$WEB_SYSTEM" "$TPL.stpl"
|
||||
fi
|
||||
|
||||
# Rebuilding proxy configuration
|
||||
if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ]; then
|
||||
del_web_config "$PROXY_SYSTEM" "$PROXY.tpl"
|
||||
add_web_config "$PROXY_SYSTEM" "$PROXY.tpl"
|
||||
if [ "$SSL" = 'yes' ]; then
|
||||
del_web_config "$PROXY_SYSTEM" "$PROXY.stpl"
|
||||
add_web_config "$PROXY_SYSTEM" "$PROXY.stpl"
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding new alias
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$ALIAS' "$ALIAS"
|
||||
increase_user_value "$user" '$U_WEB_ALIASES'
|
||||
|
||||
# Restarting web server
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
|
||||
# Restarting proxy server
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Added new web domain alias (Alias: $aliases, Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,71 @@
|
||||
#!/bin/bash
|
||||
# info: Allow other users create subdomains
|
||||
# options: USER DOMAIN
|
||||
#
|
||||
# example: v-add-web-domain-allow-users admin admin.com
|
||||
#
|
||||
# Bypass the rule check for Enforce subdomain ownership for a specific domain.
|
||||
# Enforce subdomain ownership setting in /edit/server/ set to no will always overwrite this behaviour
|
||||
# eg: admin adds admin.com
|
||||
# user can create user.admin.com
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN'
|
||||
is_format_valid 'user' 'domain'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Load domain data
|
||||
parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf)
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ -z "$ALLOW_USERS" ]; then
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'ALLOW_USERS' 'TIME'
|
||||
fi
|
||||
|
||||
# Adding new alias
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$ALLOW_USERS' "yes"
|
||||
|
||||
$BIN/v-log-action "$user" "Warning" "Web" "Subdomain ownership enforcement disabled (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,97 @@
|
||||
#!/bin/bash
|
||||
# info: add web domain backend
|
||||
# options: USER DOMAIN [TEMPLATE] [RESTART]
|
||||
#
|
||||
# example: v-add-web-domain-backend admin example.com default yes
|
||||
#
|
||||
# This function is used to add the web backend configuration.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
template=${3-default}
|
||||
restart=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/conf/hestia.conf
|
||||
source $HESTIA/conf/hestia.conf
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN [TEMPLATE] [RESTART]'
|
||||
is_format_valid 'user' 'domain'
|
||||
is_system_enabled "$WEB_BACKEND" 'WEB_BACKEND'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_backend_template_valid "$template"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Defining pool directory
|
||||
prepare_web_backend
|
||||
get_domain_values 'web'
|
||||
|
||||
if [[ -n "$BACKEND" && "$BACKEND" != "$template" ]]; then
|
||||
check_result "$E_EXISTS" "Pool already exists"
|
||||
fi
|
||||
|
||||
# Allocating backend port
|
||||
backend_port=9000
|
||||
ports=$(grep -v '^;' $pool/* 2> /dev/null | grep listen | grep -o :[0-9].*)
|
||||
ports=$(echo "$ports" | sed "s/://" | sort -n)
|
||||
for port in $ports; do
|
||||
if [ "$backend_port" -eq "$port" ]; then
|
||||
backend_port=$((backend_port + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
# Adding backend config
|
||||
cat $WEBTPL/$WEB_BACKEND/$template.tpl \
|
||||
| sed -e "s|%backend_port%|$backend_port|" \
|
||||
-e "s|%user%|$user|g" \
|
||||
-e "s|%domain%|$domain|g" \
|
||||
-e "s|%backend%|$backend_type|g" \
|
||||
-e "s|%backend_version%|$backend_version|g" > $pool/$backend_type.conf
|
||||
|
||||
# Set correct document root path
|
||||
if [ -n "$CUSTOM_DOCROOT" ]; then
|
||||
docroot="$CUSTOM_DOCROOT"
|
||||
if [ -n "$CUSTOM_PHPROOT" ]; then
|
||||
docroot="$CUSTOM_PHPROOT"
|
||||
fi
|
||||
sed -i "s|/home\/$user\/web\/$domain\/public_html|$docroot|g" $pool/$backend_type.conf
|
||||
else
|
||||
docroot="$HOMEDIR/$user/web/$domain/public_html/"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Restart php interpreter
|
||||
$BIN/v-restart-web-backend "$restart" "$backend_version"
|
||||
check_result $? "PHP restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Web domain configuration applied (Domain: $domain, Backend: $WEB_BACKEND)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,140 @@
|
||||
#!/bin/bash
|
||||
# info: add ftp account for web domain.
|
||||
# options: USER DOMAIN FTP_USER FTP_PASSWORD [FTP_PATH]
|
||||
#
|
||||
# example: v-add-web-domain-ftp alice wonderland.com alice_ftp p4$$vvOrD
|
||||
#
|
||||
# This function creates additional ftp account for web domain.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
ftp_user=${1}_${3}
|
||||
password=$4
|
||||
HIDE=4
|
||||
ftp_path=$5
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '4' "$#" 'USER DOMAIN FTP_USER FTP_PASSWORD [FTP_PATH]'
|
||||
is_format_valid 'user' 'domain' 'ftp_user'
|
||||
is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
check_ftp_user=$(grep "^$ftp_user:" /etc/passwd)
|
||||
if [ -n "$check_ftp_user" ] && [ "$FTP_USER" != "$ftp_user" ]; then
|
||||
echo "Error: ftp user $ftp_user already exists"
|
||||
log_event "$E_EXISTS" "$ARGUMENTS"
|
||||
exit "$E_EXISTS"
|
||||
fi
|
||||
is_password_valid
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Get domain values
|
||||
get_domain_values 'web'
|
||||
|
||||
# Defining ftp user shell
|
||||
shell=$(which nologin)
|
||||
if [ -n "$FTP_SHELL" ]; then
|
||||
shell=$FTP_SHELL
|
||||
fi
|
||||
|
||||
# Defining path
|
||||
if [ -z "$ftp_path" ]; then
|
||||
ftp_path_a="$HOMEDIR/$user/web/$domain"
|
||||
else
|
||||
# Validating absolute path
|
||||
ftp_path_a=$(readlink -f "$HOMEDIR/$user/web/$domain/$ftp_path")
|
||||
if [ -z "$(echo $ftp_path_a | grep $HOMEDIR/$user/web/$domain)" ]; then
|
||||
echo "Error: absolute path $ftp_path_a is invalid"
|
||||
log_event "$E_INVALID" "$ARGUMENTS"
|
||||
exit "$E_INVALID"
|
||||
fi
|
||||
# Creating ftp user home directory
|
||||
if [ ! -e "$ftp_path_a" ]; then
|
||||
$BIN/v-add-fs-directory "$user" "$ftp_path_a"
|
||||
chown $user:$user "$ftp_path_a"
|
||||
chmod 751 "$ftp_path_a"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Adding ftp user
|
||||
/usr/sbin/useradd $ftp_user \
|
||||
-s $shell \
|
||||
-o -u $(id -u $user) \
|
||||
-g $(id -g $user) \
|
||||
-G hestia-users \
|
||||
-M -d "$ftp_path_a" > /dev/null 2>&1
|
||||
|
||||
# Set ftp user password
|
||||
echo "$ftp_user:$password" | /usr/sbin/chpasswd
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
# Delete user on failure again
|
||||
/usr/sbin/deluser "$ftp_user" > /dev/null 2>&1
|
||||
echo "Error: Password not accepted due to PAM restrictions"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
ftp_md5=$(awk -v user=$ftp_user -F : 'user == $1 {print $2}' /etc/shadow)
|
||||
|
||||
# Adding jailed sftp env
|
||||
$BIN/v-add-user-sftp-jail "$ftp_user"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Transforming absolute path to relative
|
||||
ftp_path_r=$(echo $ftp_path_a | sed "s%$HOMEDIR/$user/web/$domain%%")
|
||||
|
||||
# Concatenating ftp variables
|
||||
if [ ! -z "$FTP_USER" ]; then
|
||||
ftp_user="$FTP_USER:$ftp_user"
|
||||
ftp_md5="$FTP_MD5:$ftp_md5"
|
||||
ftp_path="$FTP_PATH:$ftp_path_r"
|
||||
fi
|
||||
|
||||
# Adding new key into web.conf
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'FTP_PATH' 'PROXY'
|
||||
|
||||
# Updating config
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$FTP_USER' "$ftp_user"
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$FTP_MD5' "$ftp_md5"
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$FTP_PATH' "$ftp_path"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Added new FTP account (Name: ${1}_${3}@$domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,125 @@
|
||||
#!/bin/bash
|
||||
# info: add password protection for web domain
|
||||
# options: USER DOMAIN AUTH_USER AUTH_PASSWORD [RESTART]
|
||||
#
|
||||
# example: v-add-web-domain-httpauth admin acme.com user02 super_pass
|
||||
#
|
||||
# This function is used for securing web domain with http auth
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
auth_user=$3
|
||||
password=$4
|
||||
HIDE=4
|
||||
restart=${5-yes}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Defining htpasswd file
|
||||
htpasswd="$HOMEDIR/$user/conf/web/$domain/htpasswd"
|
||||
docroot="$HOMEDIR/$user/web/$domain/public_html"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '4' "$#" 'USER DOMAIN AUTH_USER AUTH_PASSWORD [RESTART]'
|
||||
is_format_valid 'user' 'domain'
|
||||
is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
is_password_valid
|
||||
get_domain_values 'web'
|
||||
is_user_format_valid "$auth_user" "Auth user"
|
||||
if [ -n "$(echo "$AUTH_USER" | tr : '\n' | grep ^$auth_user$)" ]; then
|
||||
echo "Error: auth user $auth_user already exists"
|
||||
log_event "$E_EXISTS" "$ARGUMENTS"
|
||||
exit "$E_EXISTS"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding htaccess password protection
|
||||
if [ "$WEB_SYSTEM" = "nginx" ] || [ "$PROXY_SYSTEM" = "nginx" ]; then
|
||||
htaccess="$HOMEDIR/$user/conf/web/$domain/nginx.conf_htaccess"
|
||||
shtaccess="$HOMEDIR/$user/conf/web/$domain/nginx.ssl.conf_htaccess"
|
||||
if [ ! -f "$htaccess" ]; then
|
||||
echo "auth_basic \"$domain password access\";" > $htaccess
|
||||
echo "auth_basic_user_file $htpasswd;" >> $htaccess
|
||||
ln -s $htaccess $shtaccess
|
||||
restart_required='yes'
|
||||
fi
|
||||
else
|
||||
htaccess="$HOMEDIR/$user/conf/web/$domain/apache2.conf_htaccess"
|
||||
shtaccess="$HOMEDIR/$user/conf/web/$domain/apache2.ssl.conf_htaccess"
|
||||
if [ ! -f "$htaccess" ]; then
|
||||
echo "<Directory $docroot>" > $htaccess
|
||||
echo " AuthUserFile $htpasswd" >> $htaccess
|
||||
echo " AuthName \"$domain access\"" >> $htaccess
|
||||
echo " AuthType Basic" >> $htaccess
|
||||
echo " Require valid-user" >> $htaccess
|
||||
echo "</Directory>" >> $htaccess
|
||||
ln -s $htaccess $shtaccess
|
||||
restart_required='yes'
|
||||
fi
|
||||
fi
|
||||
|
||||
# Adding httpasswd user
|
||||
auth_hash=$($BIN/v-generate-password-hash htpasswd htpasswd $password)
|
||||
touch $htpasswd
|
||||
chmod 644 $htpasswd $htaccess
|
||||
chgrp $user $htpasswd $htaccess
|
||||
sed -i "/^$auth_user:/d" $htpasswd
|
||||
echo "$auth_user:$auth_hash" >> $htpasswd
|
||||
|
||||
# Restarting web server
|
||||
if [ "$restart" != 'no' ] && [ "$restart_required" = 'yes' ]; then
|
||||
$BIN/v-restart-web
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
$BIN/v-restart-proxy
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Preparing web.conf keys
|
||||
if [ -n "$AUTH_USER" ]; then
|
||||
auth_user="$AUTH_USER:$auth_user"
|
||||
auth_hash="$AUTH_HASH:$auth_hash"
|
||||
else
|
||||
# Adding new key into web.conf
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'AUTH_USER' 'U_DISK'
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'AUTH_HASH' 'U_DISK'
|
||||
fi
|
||||
|
||||
# Updating config
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$AUTH_USER' "$auth_user"
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$AUTH_HASH' "$auth_hash"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Password protection enabled (Domain: $domain, Username: $httpauth_user)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,88 @@
|
||||
#!/bin/bash
|
||||
# info: add webdomain proxy support
|
||||
# options: USER DOMAIN [TEMPLATE] [EXTENTIONS] [RESTART]
|
||||
#
|
||||
# example: v-add-web-domain-proxy admin example.com
|
||||
#
|
||||
# This function enables proxy support for a domain. This can significantly
|
||||
# improve website speed.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
template=$3
|
||||
default_extentions="jpg,jpeg,gif,png,webp,ico,svg,css,zip,tgz,gz,rar,bz2,doc,xls,\
|
||||
exe,pdf,ppt,txt,odt,ods,odp,odf,tar,wav,bmp,rtf,js,mp3,avi,mpeg,flv,html,htm"
|
||||
extentions=${4-$default_extentions}
|
||||
restart="$5"
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN [TEMPLATE] [EXTENTIONS] [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'extentions'
|
||||
is_system_enabled "$PROXY_SYSTEM" 'PROXY_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
is_object_value_empty 'web' 'DOMAIN' "$domain" '$PROXY'
|
||||
if [ -z $template ]; then
|
||||
template=$(get_user_value '$PROXY_TEMPLATE')
|
||||
fi
|
||||
is_proxy_template_valid $template
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Defining domain parameters
|
||||
get_domain_values 'web'
|
||||
prepare_web_domain_values
|
||||
local_ip=$(get_real_ip "$IP")
|
||||
|
||||
# Preparing domain values for the template substitution
|
||||
PROXY_EXT="$extentions"
|
||||
add_web_config "$PROXY_SYSTEM" "$template.tpl"
|
||||
|
||||
# Adding proxy for ssl
|
||||
if [ "$SSL" = 'yes' ]; then
|
||||
add_web_config "$PROXY_SYSTEM" "$template.stpl"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Update config
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$PROXY' "$template"
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$PROXY_EXT' "$extentions"
|
||||
|
||||
# Restarting web server
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Proxy enabled (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,162 @@
|
||||
#!/bin/bash
|
||||
# info: Adding force redirect to domain
|
||||
# options: USER DOMAIN REDIRECT HTTPCODE [RESTART]
|
||||
#
|
||||
# example: v-add-web-domain-redirect user domain.tld domain.tld
|
||||
# example: v-add-web-domain-redirect user domain.tld www.domain.tld
|
||||
# example: v-add-web-domain-redirect user domain.tld shop.domain.tld
|
||||
# example: v-add-web-domain-redirect user domain.tld different-domain.com
|
||||
# example: v-add-web-domain-redirect user domain.tld shop.different-domain.com
|
||||
# example: v-add-web-domain-redirect user domain.tld different-domain.com 302
|
||||
#
|
||||
# Function creates a forced redirect to a domain
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
redirect=$3
|
||||
code=${4-301}
|
||||
restart=${5-no}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN REDIRECT [HTTP-CODE] [RESTART]'
|
||||
is_format_valid 'user' 'domain'
|
||||
is_number_format_valid "$code" "code"
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
|
||||
requesturi=0
|
||||
if [[ "$3" =~ http://|https:// ]]; then
|
||||
scheme_check=1
|
||||
scheme=$($HESTIA_PHP -r '$url=parse_url($argv[1]); echo $url["scheme"];' "$redirect")
|
||||
host=$($HESTIA_PHP -r '$url=parse_url($argv[1]); echo $url["host"];' "$redirect")
|
||||
path=$($HESTIA_PHP -r '$url=parse_url($argv[1]); if(!empty($url["path"])){echo $url["path"];}' "$redirect")
|
||||
port=$($HESTIA_PHP -r '$url=parse_url($argv[1]); if(!empty($url["port"])){echo $url["port"];}' "$redirect")
|
||||
|
||||
host=$(idn2 --quiet "$host")
|
||||
redirect="$scheme://$host$path"
|
||||
if [ -n "$port" ]; then
|
||||
redirect="$scheme://$host:$port$path"
|
||||
fi
|
||||
|
||||
isValidUrl=$(php -r '$url=$argv[1]; $url=filter_var($url,FILTER_VALIDATE_URL); echo $url;' "$redirect")
|
||||
if [ -z "$isValidUrl" ]; then
|
||||
check_result $E_INVALID "Invalid redirect"
|
||||
fi
|
||||
else
|
||||
host=$($HESTIA_PHP -r '$url=parse_url($argv[1]); echo $url["host"];' "http://$redirect")
|
||||
path=$($HESTIA_PHP -r '$url=parse_url($argv[1]); if(!empty($url["path"])){echo $url["path"];}' "http://$redirect")
|
||||
port=$($HESTIA_PHP -r '$url=parse_url($argv[1]); if(!empty($url["port"])){echo $url["port"];}' "$redirect")
|
||||
|
||||
host=$(idn2 --quiet "$host")
|
||||
|
||||
redirect="$host$path"
|
||||
if [ -n "$port" ]; then
|
||||
redirect="$host:$port$path"
|
||||
fi
|
||||
|
||||
isValidUrl=$(php -r '$url=$argv[1]; $url=filter_var($url,FILTER_VALIDATE_URL); echo $url;' "http://$redirect")
|
||||
if [ -z "$isValidUrl" ]; then
|
||||
check_result $E_INVALID "Invalid redirect"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Check if proxy is active
|
||||
if [ "$WEB_SYSTEM" = 'nginx' ] || [ "$PROXY_SYSTEM" = 'nginx' ]; then
|
||||
conf="$HOMEDIR/$user/conf/web/$domain/nginx.conf_redirect"
|
||||
sconf="$HOMEDIR/$user/conf/web/$domain/nginx.ssl.conf_redirect"
|
||||
fi
|
||||
|
||||
# Prevent $request_uri being added if ends in .html
|
||||
requesturi=0
|
||||
if [ -n "$path" ]; then
|
||||
lastchr=${path#${path%?}}
|
||||
if [ "$lastchr" = "/" ]; then
|
||||
requesturi=1
|
||||
redirect=${redirect:0:-1}
|
||||
fi
|
||||
else
|
||||
requesturi=1
|
||||
fi
|
||||
|
||||
# Insert redirect commands
|
||||
if [ -n "$PROXY_SYSTEM" ] || [ "$WEB_SYSTEM" = 'nginx' ]; then
|
||||
if [ "$scheme_check" = 1 ]; then
|
||||
if [ "$requesturi" = 1 ]; then
|
||||
echo " return $code $redirect\$request_uri;" > $conf
|
||||
else
|
||||
echo " return $code $redirect;" > $conf
|
||||
fi
|
||||
if [ ! -e "$sconf" ]; then
|
||||
ln -s "$conf" "$sconf"
|
||||
fi
|
||||
else
|
||||
echo "if (\$host != \"$redirect\") {" > $conf
|
||||
if [ "$requesturi" = 1 ]; then
|
||||
echo " return $code \$scheme://$redirect\$request_uri;" >> $conf
|
||||
else
|
||||
echo " return $code \$scheme://$redirect;" >> $conf
|
||||
fi
|
||||
echo "}" >> $conf
|
||||
|
||||
if [ ! -e "$sconf" ]; then
|
||||
ln -s "$conf" "$sconf"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "Non supported please use .htaccess instead"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Update object keys
|
||||
if [ -z "$REDIRECT" ]; then
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'REDIRECT' 'U_DISK'
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'REDIRECT_CODE' 'U_DISK'
|
||||
fi
|
||||
|
||||
# Update values for domain
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$REDIRECT' "$redirect"
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$REDIRECT_CODE' "$code"
|
||||
|
||||
if [ "$restart" = "yes" ]; then
|
||||
# Restarting web server
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
fi
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Domain redirection enabled (Domain: $domain, Redirect to: $redirect)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,143 @@
|
||||
#!/bin/bash
|
||||
# info: adding ssl for domain
|
||||
# options: USER DOMAIN SSL_DIR [SSL_HOME] [RESTART]
|
||||
#
|
||||
# example: v-add-web-domain-ssl admin example.com /home/admin/conf/example.com/web
|
||||
#
|
||||
# This function turns on SSL support for a domain. Parameter ssl_dir is a path
|
||||
# to directory where 2 or 3 ssl files can be found. Certificate file
|
||||
# domain.tld.crt and its key domain.tld.key are mandatory. Certificate
|
||||
# authority domain.tld.ca file is optional. If home directory parameter
|
||||
# (ssl_home) is not set, https domain uses public_shtml as separate
|
||||
# documentroot directory.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
ssl_dir=$3
|
||||
ssl_home=${4-same}
|
||||
restart="$5"
|
||||
|
||||
domain=$domain
|
||||
domain_idn=$(idn2 --quiet "$domain")
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN SSL_DIR [SSL_HOME] [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'ssl_dir'
|
||||
is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
|
||||
is_system_enabled "$WEB_SSL" 'SSL_SUPPORT'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
is_object_value_empty 'web' 'DOMAIN' "$domain" '$SSL'
|
||||
is_web_domain_cert_valid
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding certificate to user data directory
|
||||
cp -f $ssl_dir/$domain.crt $USER_DATA/ssl/$domain.crt
|
||||
cp -f $ssl_dir/$domain.key $USER_DATA/ssl/$domain.key
|
||||
cp -f $ssl_dir/$domain.crt $USER_DATA/ssl/$domain.pem
|
||||
if [ -e "$ssl_dir/$domain.ca" ]; then
|
||||
cp -f $ssl_dir/$domain.ca $USER_DATA/ssl/$domain.ca
|
||||
echo >> $USER_DATA/ssl/$domain.pem
|
||||
cat $USER_DATA/ssl/$domain.ca >> $USER_DATA/ssl/$domain.pem
|
||||
fi
|
||||
chmod 660 $USER_DATA/ssl/$domain.*
|
||||
|
||||
# Ensure SSL directory exists
|
||||
if [ ! -d "$HOMEDIR/$user/conf/web/$domain/ssl" ]; then
|
||||
mkdir -p $HOMEDIR/$user/conf/web/$domain/ssl/
|
||||
fi
|
||||
|
||||
# Adding certificate to user dir
|
||||
cp -f $USER_DATA/ssl/$domain.crt $HOMEDIR/$user/conf/web/$domain/ssl/$domain.crt
|
||||
cp -f $USER_DATA/ssl/$domain.key $HOMEDIR/$user/conf/web/$domain/ssl/$domain.key
|
||||
cp -f $USER_DATA/ssl/$domain.pem $HOMEDIR/$user/conf/web/$domain/ssl/$domain.pem
|
||||
if [ -e "$USER_DATA/ssl/$domain.ca" ]; then
|
||||
cp -f $USER_DATA/ssl/$domain.ca $HOMEDIR/$user/conf/web/$domain/ssl/$domain.ca
|
||||
fi
|
||||
|
||||
if [ "$SSL_FORCE" == "yes" ]; then
|
||||
# Enabling SSL redirection on demand
|
||||
$BIN/v-add-web-domain-ssl-force "$user" "$domain"
|
||||
fi
|
||||
# Parsing domain values
|
||||
get_domain_values 'web'
|
||||
local_ip=$(get_real_ip "$IP")
|
||||
|
||||
# Preparing domain values for the template substitution
|
||||
SSL_HOME="$ssl_home"
|
||||
prepare_web_domain_values
|
||||
|
||||
# Adding domain to the web config
|
||||
add_web_config "$WEB_SYSTEM" "$TPL.stpl"
|
||||
|
||||
# Checking proxy config
|
||||
if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ]; then
|
||||
add_web_config "$PROXY_SYSTEM" "$PROXY.stpl"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Increasing domain value
|
||||
increase_user_value "$user" '$U_WEB_SSL'
|
||||
|
||||
# Adding ssl values
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$SSL_HOME' "$SSL_HOME"
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$SSL' "yes"
|
||||
|
||||
# Restarting web server
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
|
||||
if [ -n "$UPDATE_HOSTNAME_SSL" ] && [ "$UPDATE_HOSTNAME_SSL" = "yes" ]; then
|
||||
hostname=$(hostname -f)
|
||||
if [ "$hostname" = "$domain" ]; then
|
||||
$BIN/v-update-host-certificate "$user" "$domain"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$UPDATE_SSL_SCRIPT" ]; then
|
||||
eval "$UPDATE_SSL_SCRIPT $user $domain"
|
||||
fi
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Added certificate and enabled SSL (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,97 @@
|
||||
#!/bin/bash
|
||||
# info: Adding force SSL for a domain
|
||||
# options: USER DOMAIN [RESTART] [QUIET]
|
||||
#
|
||||
# example: v-add-web-domain-ssl-force admin acme.com
|
||||
#
|
||||
# This function forces SSL for the requested domain.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
restart="$3"
|
||||
quiet="$4"
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN'
|
||||
is_format_valid 'user' 'domain'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Load domain data
|
||||
parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf)
|
||||
|
||||
# Check if SSL is enabled
|
||||
if [ "$SSL" != 'yes' ]; then
|
||||
echo "Error: SSL is not enabled"
|
||||
exit "$E_NOTEXIST"
|
||||
fi
|
||||
|
||||
# Check if proxy is active
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
forcessl="$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.forcessl.conf"
|
||||
else
|
||||
forcessl="$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.forcessl.conf"
|
||||
fi
|
||||
|
||||
# Insert redirect commands
|
||||
if [ -n "$PROXY_SYSTEM" ] || [ "$WEB_SYSTEM" = 'nginx' ]; then
|
||||
echo 'return 301 https://$host$request_uri;' > $forcessl
|
||||
else
|
||||
echo 'RewriteEngine On' > $forcessl
|
||||
echo 'RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]' >> $forcessl
|
||||
fi
|
||||
|
||||
chown root:$user $forcessl
|
||||
chmod 640 $forcessl
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ -z "$SSL_FORCE" ]; then
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'SSL_FORCE' 'SSL_HOME'
|
||||
fi
|
||||
|
||||
# Set forcessl flag to enabled
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$SSL_FORCE' 'yes'
|
||||
|
||||
# Restart web server
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
|
||||
# Restart proxy
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
if [ "$quiet" != "yes" ]; then
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Automatic HTTPS redirection enabled (Domain: $domain)."
|
||||
fi
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,89 @@
|
||||
#!/bin/bash
|
||||
# info: Adding hsts to a domain
|
||||
# options: USER DOMAIN [RESTART] [QUIET]
|
||||
#
|
||||
# This function enables HSTS for the requested domain.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
restart="$3"
|
||||
quiet="$4"
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN'
|
||||
is_format_valid 'user' 'domain'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Load domain data
|
||||
parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf)
|
||||
|
||||
# Check if SSL is enabled
|
||||
if [ "$SSL" != 'yes' ]; then
|
||||
echo "Error: SSL is not enabled"
|
||||
exit "$E_NOTEXIST"
|
||||
fi
|
||||
|
||||
# Check for Apache/Nginx or Nginx/PHP-FPM configuration
|
||||
if [ -z "$PROXY_SYSTEM" ]; then
|
||||
hstsconf="$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.hsts.conf"
|
||||
else
|
||||
hstsconf="$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.hsts.conf"
|
||||
fi
|
||||
|
||||
echo 'add_header Strict-Transport-Security "max-age=31536000;" always;' > $hstsconf
|
||||
|
||||
chown root:$user $hstsconf
|
||||
chmod 640 $hstsconf
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ -z "$SSL_HSTS" ]; then
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'SSL_HSTS' 'SSL_FORCE'
|
||||
fi
|
||||
|
||||
# Set forcessl flag to enabled
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$SSL_HSTS' 'yes'
|
||||
|
||||
# Restart web server
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
|
||||
# Restart proxy
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
if [ "$quiet" != "yes" ]; then
|
||||
$BIN/v-log-action "$user" "Info" "Web" "HTTP Strict Transport Security (HSTS) enabled (Domain: $domain)."
|
||||
fi
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,60 @@
|
||||
#!/bin/bash
|
||||
# info: Adding force SSL for a domain
|
||||
# options: USER DOMAIN [SSL]
|
||||
#
|
||||
# example: v-add-web-domain-ssl-preset
|
||||
#
|
||||
# Up on creating an web domain set the SSL Force values due to the delay of LE due to DNS propergation over DNS cluster
|
||||
# When LE has been activated it will set the actions
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
ssl=$3
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN [SSL]'
|
||||
is_format_valid 'user' 'domain' 'ssl'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Load domain data
|
||||
parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf)
|
||||
|
||||
if [ "$ssl" = "yes" ]; then
|
||||
if [ -z "$SSL_FORCE" ]; then
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'SSL_FORCE' 'SSL_HOME'
|
||||
fi
|
||||
|
||||
# Set forcessl flag to enabled
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$SSL_FORCE' 'yes'
|
||||
fi
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,109 @@
|
||||
#!/bin/bash
|
||||
# info: add log analyser to generate domain statistics
|
||||
# options: USER DOMAIN TYPE
|
||||
#
|
||||
# example: v-add-web-domain-stats admin example.com awstats
|
||||
#
|
||||
# This function is used for enabling log analyser system to a domain. For viewing
|
||||
# the domain statistics use <http://domain.tld/vstats/> link. Access this page
|
||||
# is not protected by default. If you want to secure it with passwords you
|
||||
# should use v-add-web-domain_stat_auth script.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
type=$3
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN TYPE'
|
||||
is_format_valid 'user' 'domain'
|
||||
is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
|
||||
is_type_valid "$STATS_SYSTEM" "$type"
|
||||
is_object_valid 'user' 'USER' "$user" "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
is_object_value_empty 'web' 'DOMAIN' "$domain" '$STATS'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Parse aliases
|
||||
get_domain_values 'web'
|
||||
|
||||
# Adding statistic config
|
||||
prepare_web_domain_values
|
||||
|
||||
if [ -z "${aliases//,/ }" ]; then
|
||||
stats_alias="localhost"
|
||||
else
|
||||
stats_alias=${aliases_idn//,/ }
|
||||
fi
|
||||
|
||||
cat $WEBTPL/$type/$type.tpl \
|
||||
| sed -e "s|%ip%|$ip|g" \
|
||||
-e "s|%web_port%|$WEB_PORT|g" \
|
||||
-e "s|%web_system%|$WEB_SYSTEM|g" \
|
||||
-e "s|%web_ssl_port%|$WEB_SSL_PORT|g" \
|
||||
-e "s|%rgroups%|$WEB_RGROUPs|g" \
|
||||
-e "s|%proxy_system%|$PROXY_SYSTEM|g" \
|
||||
-e "s|%proxy_port%|$PROXY_PORT|g" \
|
||||
-e "s|%proxy_ssl_port%|$PROXY_SSL_PORT|g" \
|
||||
-e "s|%domain_idn%|$domain_idn|g" \
|
||||
-e "s|%domain%|$domain|g" \
|
||||
-e "s|%user%|$user|g" \
|
||||
-e "s|%home%|$HOMEDIR|g" \
|
||||
-e "s|%alias%|$stats_alias|g" \
|
||||
-e "s|%alias_idn%|$stats_alias|g" \
|
||||
> $HOMEDIR/$user/conf/web/$domain/$type.conf
|
||||
|
||||
if [ "$type" == 'awstats' ]; then
|
||||
rm -f /etc/awstats/$type.$domain_idn.conf
|
||||
ln -s $HOMEDIR/$user/conf/web/$domain/$type.conf \
|
||||
/etc/awstats/$type.$domain_idn.conf
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Schedule statistic processing
|
||||
echo "$BIN/v-update-web-domain-stat $user $domain" >> $HESTIA/data/queue/webstats.pipe
|
||||
|
||||
# Update config
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$STATS' "$type"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Web traffic analyzer enabled (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
# Build stats
|
||||
exec $BIN/v-update-web-domain-stat "$user" "$domain"
|
||||
|
||||
exit
|
@ -0,0 +1,89 @@
|
||||
#!/bin/bash
|
||||
# info: add password protection to web domain statistics
|
||||
# options: USER DOMAIN STATS_USER STATS_PASSWORD [RESTART]
|
||||
#
|
||||
# example: v-add-web-domain-stats-user admin example.com watchdog your_password
|
||||
#
|
||||
# This function is used for securing the web statistics page.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
stats_user=$3
|
||||
password=$4
|
||||
HIDE=4
|
||||
restart=$5
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '4' "$#" 'USER DOMAIN STATS_USER STATS_PASS [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'stats_user'
|
||||
is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
is_password_valid
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Defining statistic dir
|
||||
stats_dir="$HOMEDIR/$user/web/$domain/stats"
|
||||
conf_dir="$HOMEDIR/$user/conf/web"
|
||||
|
||||
# Adding htaccess file
|
||||
if [ "$WEB_SYSTEM" = 'nginx' ]; then
|
||||
echo "auth_basic \"Web Statistics\";" > $stats_dir/auth.conf
|
||||
echo "auth_basic_user_file $stats_dir/.htpasswd;" >> $stats_dir/auth.conf
|
||||
else
|
||||
echo "AuthUserFile $stats_dir/.htpasswd" > $stats_dir/.htaccess
|
||||
echo "AuthName \"Web Statistics\"" >> $stats_dir/.htaccess
|
||||
echo "AuthType Basic" >> $stats_dir/.htaccess
|
||||
echo "Require valid-user" >> $stats_dir/.htaccess
|
||||
fi
|
||||
|
||||
# Generating htaccess user and password
|
||||
salt=$(generate_password "$PW_MATRIX" "8")
|
||||
stats_pass=$($BIN/v-generate-password-hash md5 $salt $password)
|
||||
echo "$stats_user:$stats_pass" > $stats_dir/.htpasswd
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding stats user in config
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$STATS_USER' "$stats_user"
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$STATS_CRYPT' "$stats_pass"
|
||||
|
||||
# Restarting web server
|
||||
if [ "$WEB_SYSTEM" = 'nginx' ]; then
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
fi
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Web traffic analyzer password enabled (Username: $stats_user, Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,194 @@
|
||||
#!/bin/bash
|
||||
# info: add php fpm version
|
||||
# options: VERSION
|
||||
#
|
||||
# example: v-add-web-php 8.0
|
||||
#
|
||||
# Install php-fpm for provided version.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
version=$1
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
source_conf "$HESTIA/install/upgrade/upgrade.conf"
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'VERSION'
|
||||
|
||||
if [ -z "$WEB_BACKEND" ]; then
|
||||
echo "Multiple php versions are not supported for modphp"
|
||||
fi
|
||||
|
||||
# Set file locations
|
||||
php_fpm="/etc/init.d/php$version-fpm"
|
||||
|
||||
# Verify php version format
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
if [[ ! $version =~ ^[0-9][0-9]+ ]]; then
|
||||
echo "The specified PHP version format is invalid, it should look like [0-9][0-9]."
|
||||
echo "Example: 70, 74, 80"
|
||||
exit "$E_INVALID"
|
||||
fi
|
||||
else
|
||||
if [[ ! $version =~ ^[0-9].[0-9]+ ]]; then
|
||||
echo "The specified PHP version format is invalid, it should look like [0-9].[0-9]."
|
||||
echo "Example: 7.0, 7.4, 8.0"
|
||||
exit "$E_INVALID"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check if php version already exists
|
||||
if [ -f "$php_fpm" ] && [ -f "$HESTIA/data/templates/web/php-fpm/PHP-${version/\./_}.tpl" ]; then
|
||||
echo "ERROR: Specified PHP version is already installed."
|
||||
exit "$E_INVALID"
|
||||
fi
|
||||
|
||||
# Check if php version is supported
|
||||
if [[ ! "$multiphp_v" =~ $version ]]; then
|
||||
echo "ERROR: Specified PHP version is not supported or does not exist."
|
||||
exit "$E_INVALID"
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
mph="php$version-common php$version-mbstring php$version-bcmath php$version-cli php$version-curl
|
||||
php$version-fpm php$version-gd php$version-intl php$version-mysql
|
||||
php$version-soap php$version-xml php$version-zip php$version-json php$version-bz2
|
||||
php$version-pspell php$version-imagick php$version-pgsql php$version-imap php$version-ldap"
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
# Packages in Remi repo have names with php$version-php- prefixes
|
||||
mph="php$version-php-fpm php$version-php-cgi php$version-php-mysqlnd php$version-php-pgsql
|
||||
php$version-php-pdo php$version-php-common php$version-php-pecl-imagick php$version-php-imap
|
||||
php$version-php-ldap php$version-php-pecl-apcu php$version-php-pecl-zip php$version-php-cli
|
||||
php$version-php-opcache php$version-php-xml php$version-php-gd php$version-php-intl
|
||||
php$version-php-mbstring php$version-php-pspell php$version-php-readline"
|
||||
if [ "$version" = "56" ]; then
|
||||
mph=$(sed -e "s/php$version-php-pecl-apcu//")
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check is version is 7.1 or below to add mcrypt
|
||||
if [[ $(echo "$version 7.2" | awk '{print ($1 < $2)}') == 1 ]]; then
|
||||
mph="$mph php$version-mcrypt"
|
||||
fi
|
||||
|
||||
# Check if version is 8.0 or higher and drop php json.
|
||||
if [[ ${version:0:1} == "8" ]]; then
|
||||
mph=$(echo "$mph" | sed -e "s/php$version\(-php\)\{0,1\}-json//")
|
||||
fi
|
||||
|
||||
if ! echo "$DB_SYSTEM" | grep -w 'mysql' > /dev/null; then
|
||||
mph=$(echo "$mph" | sed -e "s/php$version\(-php\)\{0,1\}-mysql//")
|
||||
fi
|
||||
|
||||
if ! echo "$DB_SYSTEM" | grep -w 'pgsql' > /dev/null; then
|
||||
mph=$(echo "$mph" | sed -e "s/php$version\(-php\)\{0,1\}-pgsql//")
|
||||
fi
|
||||
|
||||
# Install php packages
|
||||
if [ -f '/etc/redhat-release' ]; then
|
||||
dnf install -q -y $mph > /dev/null 2>&1 &
|
||||
else
|
||||
apt-get -qq update
|
||||
apt-get -y -qq -o Dpkg::Options::="--force-confold" install $mph > /dev/null 2>&1 &
|
||||
fi
|
||||
BACK_PID=$!
|
||||
|
||||
# Check if package installation is done, print a spinner
|
||||
echo "Installing PHP-$version, please wait..."
|
||||
spinner="/-\|"
|
||||
spin_i=1
|
||||
while kill -0 $BACK_PID > /dev/null 2>&1; do
|
||||
printf "\b${spinner:spin_i++%${#spinner}:1}"
|
||||
sleep 0.5
|
||||
done
|
||||
|
||||
# Do a blank echo to get the \n back
|
||||
echo
|
||||
|
||||
# Check if installation was successful
|
||||
if [ ! -f "$php_fpm" ]; then
|
||||
echo "ERROR: Installation failed, please run the following command manually for debugging:"
|
||||
if [ -f '/etc/redhat-release' ]; then
|
||||
echo "dnf install $mph"
|
||||
else
|
||||
echo "apt-get install $mph"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check if required modules for apache2 are enabled
|
||||
if [ "$WEB_SYSTEM" = "apache2" ]; then
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
if ! httpd -M | grep 'proxy_fcgi_module' ; then
|
||||
sed 's/#LoadModule proxy_fcgi_module/LoadModule proxy_fcgi_module/' -i /etc/httpd/conf.modules.d/00-proxy.conf
|
||||
sed 's/#LoadModule proxy_module/LoadModule proxy_module/' -i /etc/httpd/conf.modules.d/00-proxy.conf
|
||||
fi
|
||||
if ! httpd -M | grep 'setenvif_module' ; then
|
||||
sed 's/#LoadModule setenvif_module/LoadModule setenvif_module/' -i /etc/httpd/conf.modules.d/00-base.conf
|
||||
fi
|
||||
else
|
||||
if ! a2query -q -m proxy_fcgi; then
|
||||
a2enmod -q proxy_fcgi
|
||||
fi
|
||||
if ! a2query -q -m setenvif; then
|
||||
a2enmod -q setenvif
|
||||
fi
|
||||
fi
|
||||
$BIN/v-restart-web "yes"
|
||||
fi
|
||||
|
||||
# Configure fpm
|
||||
v_tpl=${version//./}
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
systemctl enable php${version}-php-fpm
|
||||
rm -f /etc/opt/remi/php${version}/php-fpm.d/*
|
||||
cp -f $HESTIA_INSTALL_DIR/php-fpm/dummy.conf /etc/opt/remi/php${version}/php-fpm.d/
|
||||
sed -i "s/9999/99$v_tpl/g" /etc/opt/remi/php${version}/php-fpm.d/dummy.conf
|
||||
|
||||
# Increase max upload and max post size
|
||||
sed -i "s/upload_max_filesize = 2M/upload_max_filesize = 100M/g" /etc/opt/remi/php${version}/php.ini
|
||||
sed -i "s/post_max_size = 8M/post_max_size = 100M/g" /etc/opt/remi/php${version}/php.ini
|
||||
sed -i "s/max_execution_time = 30/max_execution_time = 60/g" /etc/opt/remi/php${version}/php.ini
|
||||
else
|
||||
update-rc.d php$version-fpm defaults > /dev/null 2>&1
|
||||
rm -f /etc/php/$version/fpm/pool.d/*
|
||||
cp -f $HESTIA_INSTALL_DIR/php-fpm/dummy.conf /etc/php/$version/fpm/pool.d/
|
||||
sed -i "s/9999/99$v_tpl/g" /etc/php/$version/fpm/pool.d/dummy.conf
|
||||
cp -f $HESTIA_INSTALL_DIR/php-fpm/php-fpm.conf /etc/php/$version/fpm/
|
||||
sed -i "s/fpm_v/$version/g" /etc/php/$version/fpm/php-fpm.conf
|
||||
|
||||
# Increase max upload and max post size
|
||||
sed -i "s/upload_max_filesize = 2M/upload_max_filesize = 100M/g" /etc/php/$version/fpm/php.ini
|
||||
sed -i "s/post_max_size = 8M/post_max_size = 100M/g" /etc/php/$version/fpm/php.ini
|
||||
sed -i "s/max_execution_time = 30/max_execution_time = 60/g" /etc/php/$version/fpm/php.ini
|
||||
fi
|
||||
# Install backend template
|
||||
cp -f $HESTIA_INSTALL_DIR/php-fpm/multiphp.tpl \
|
||||
$HESTIA/data/templates/web/php-fpm/PHP-${version/\./_}.tpl
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "System" "Installed PHP $version."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,800 @@
|
||||
#!/bin/bash
|
||||
# info: backup system user with all its objects
|
||||
# options: USER NOTIFY
|
||||
#
|
||||
# example: v-backup-user admin yes
|
||||
#
|
||||
# This function is used for backing up user with all its domains and databases.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
notify=${2-no}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/db.sh
|
||||
source $HESTIA/func/db.sh
|
||||
# shellcheck source=/usr/local/hestia/func/backup.sh
|
||||
source $HESTIA/func/backup.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Return Disk Usage
|
||||
get_user_disk_usage() {
|
||||
u_usage=0
|
||||
web_exclusions=''
|
||||
mail_exclusions=''
|
||||
db_exclusions=''
|
||||
user_exclusions=''
|
||||
|
||||
# Parsing excludes
|
||||
if [ -e "$USER_DATA/backup-excludes.conf" ]; then
|
||||
web_exclusions=$(grep 'WEB=' $USER_DATA/backup-excludes.conf \
|
||||
| awk -F "WEB='" '{print $2}' | cut -f 1 -d \')
|
||||
mail_exclusions=$(grep 'MAIL=' $USER_DATA/backup-excludes.conf \
|
||||
| awk -F "MAIL='" '{print $2}' | cut -f 1 -d \')
|
||||
db_exclusions=$(grep 'DB=' $USER_DATA/backup-excludes.conf \
|
||||
| awk -F "DB='" '{print $2}' | cut -f 1 -d \')
|
||||
user_exclusions=$(grep 'USER=' $USER_DATA/backup-excludes.conf \
|
||||
| awk -F "USER='" '{print $2}' | cut -f 1 -d \')
|
||||
fi
|
||||
|
||||
if [ -f "$USER_DATA/web.conf" ] && [ "$web_exclusions" != '*' ]; then
|
||||
usage=0
|
||||
domains=$(grep 'DOMAIN=' $USER_DATA/web.conf \
|
||||
| awk -F "DOMAIN='" '{print $2}' | cut -f 1 -d \')
|
||||
|
||||
for domain in $domains; do
|
||||
exclusion=$(echo -e "$web_exclusions" | tr ',' '\n' | grep "^$domain\|\*$")
|
||||
if [ -z "$exclusion" ]; then
|
||||
# Defining home directory
|
||||
home_dir="$HOMEDIR/$user/web/$domain/"
|
||||
exclusion=$(echo -e "$web_exclusions" | tr ',' '\n' | grep "^$domain\|\*:")
|
||||
fargs=()
|
||||
|
||||
if [ -n "$exclusion" ]; then
|
||||
xdirs=$(echo -e "$exclusion" | tr ':' '\n' | grep -v "$domain\|\*")
|
||||
for xpath in $xdirs; do
|
||||
fargs+=(--exclude="$xpath")
|
||||
done
|
||||
fi
|
||||
|
||||
# Checking home directory exist
|
||||
if [ -e "$home_dir" ]; then
|
||||
disk_usage=$(nice -n 19 du -shm "$home_dir" "${fargs[@]}" | cut -f 1)
|
||||
u_usage=$((u_usage + disk_usage))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -f "$USER_DATA/mail.conf" ] && [ "$mail_exclusions" != '*' ]; then
|
||||
usage=0
|
||||
domains=$(grep 'DOMAIN=' "$USER_DATA/mail.conf" \
|
||||
| awk -F "DOMAIN='" '{print $2}' | cut -f 1 -d \')
|
||||
|
||||
for domain in $domains; do
|
||||
check_exl=$(echo "$mail_exclusions" | tr ',' '\n' | grep "^$domain$")
|
||||
if [ -f "$USER_DATA/mail/$domain.conf" ] && [ -z "$check_exl" ]; then
|
||||
accounts=$(grep 'ACCOUNT=' "$USER_DATA/mail/$domain.conf" \
|
||||
| awk -F "ACCOUNT='" '{print $2}' | cut -f 1 -d \')
|
||||
|
||||
for account in $accounts; do
|
||||
home_dir=$HOMEDIR/$user/mail/$domain/$account
|
||||
exclusion=$(echo "$mail_exclusions" | tr ',' '\n' | grep "$domain:")
|
||||
exclusion=$(echo "$exclusion" | tr ':' '\n' | grep -E "^$account|\*")
|
||||
|
||||
if [ -z "$exclusion" ] && [ -e "$home_dir" ]; then
|
||||
disk_usage=$(nice -n 19 du -shm "$home_dir" | cut -f 1)
|
||||
u_usage=$((u_usage + disk_usage))
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -f "$USER_DATA/db.conf" ] && [ "$db_exclusions" != '*' ]; then
|
||||
usage=0
|
||||
databases=$(grep 'DB=' "$USER_DATA/db.conf" \
|
||||
| awk -F "DB='" '{print $2}' | cut -f 1 -d \')
|
||||
for database in $databases; do
|
||||
exclusion=$(echo "$db_exclusions" | tr ',' '\n' | grep "^$database$")
|
||||
if [ -z "$exclusion" ]; then
|
||||
# Get database values
|
||||
get_database_values
|
||||
|
||||
# Switching on db type
|
||||
case $DB_SYSTEM in
|
||||
mysql) get_mysql_disk_usage ;;
|
||||
pgsql) get_pgsql_disk_usage ;;
|
||||
esac
|
||||
u_usage=$((u_usage + usage))
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$user_exclusions" != '*' ]; then
|
||||
fargs=()
|
||||
for xpath in $(echo "$user_exclusions" | tr ',' '\n'); do
|
||||
fargs+=(--exclude="$xpath")
|
||||
done
|
||||
usage=$(du -shm "$HOMEDIR/$user" --exclude "$HOMEDIR/$user/web" --exclude "$HOMEDIR/$user/mail" --exclude "$HOMEDIR/$user/conf" "${fargs[@]}" | cut -f 1)
|
||||
u_usage=$((u_usage + usage))
|
||||
fi
|
||||
|
||||
echo ${u_usage}
|
||||
}
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'USER [NOTIFY]'
|
||||
is_format_valid 'user'
|
||||
is_system_enabled "$BACKUP_SYSTEM" 'BACKUP_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
if [ "$POLICY_BACKUP_SUSPENDED_USERS" != "yes" ]; then
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
fi
|
||||
is_backup_enabled
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_backup_conditions
|
||||
|
||||
# Set backup directory if undefined
|
||||
if [ -z "$BACKUP" ]; then
|
||||
BACKUP=/backup
|
||||
fi
|
||||
|
||||
# Check if backup folder exists and have the correct permission
|
||||
if [[ ! -d "$BACKUP" ]]; then
|
||||
mkdir -p $BACKUP
|
||||
fi
|
||||
if [ "$(stat -c %a "$BACKUP")" != 755 ]; then
|
||||
chmod 755 $BACKUP
|
||||
fi
|
||||
|
||||
# Get current time
|
||||
start_time=$(date '+%s')
|
||||
|
||||
# Set notification email and subject
|
||||
subj="$user → backup failed"
|
||||
email=$(grep CONTACT "$HESTIA/data/users/admin/user.conf" | cut -f 2 -d \')
|
||||
|
||||
# Validate available disk space (take usage * 2, due to the backup handling)
|
||||
let u_disk=$(($(get_user_disk_usage) * 2))
|
||||
let v_disk=$(($(stat -f --format="%a*%S" $BACKUP)))/1024/1024
|
||||
|
||||
if [ "$u_disk" -gt "$v_disk" ]; then
|
||||
let u_disk_original=$(get_user_disk_usage)
|
||||
# Always notify on failure
|
||||
echo "Not enough disk space available ($v_disk mb) to perform the backup of $user. ( $u_disk_original mb * 2 = $u_disk mb). https://hestiacp.com/docs/server-administration/backup-restore.html" | $SENDMAIL -s "$subj" "$email" "yes"
|
||||
# Deleting task from queue
|
||||
sed -i "/v-backup-user $user /d" $HESTIA/data/queue/backup.pipe
|
||||
check_result "$E_LIMIT" "not enough disk space available ($v_disk mb) to perform the backup of $user. ( $u_disk_original mb * 2 = $u_disk mb)."
|
||||
fi
|
||||
|
||||
if [ -z "$BACKUP_TEMP" ]; then
|
||||
BACKUP_TEMP=$BACKUP
|
||||
fi
|
||||
|
||||
# Creating temporary directory
|
||||
tmpdir=$(mktemp -p $BACKUP_TEMP -d)
|
||||
|
||||
if [ "$?" -ne 0 ]; then
|
||||
echo "Can't create tmp dir $tmpdir" | $SENDMAIL -s "$subj" "$email" "yes"
|
||||
# Deleting task from queue
|
||||
sed -i "/v-backup-user $user /d" $HESTIA/data/queue/backup.pipe
|
||||
check_result "$E_NOTEXIST" "can't create tmp dir"
|
||||
fi
|
||||
|
||||
# Backup sys configs
|
||||
echo "-- SYSTEM --" | tee $BACKUP/$user.log
|
||||
mkdir $tmpdir/hestia
|
||||
|
||||
echo -e "$(date "+%F %T") $user.conf" | tee -a $BACKUP/$user.log
|
||||
cp -r $USER_DATA/user.conf $tmpdir/hestia/
|
||||
cp -r $USER_DATA/ssl $tmpdir/hestia/
|
||||
|
||||
if [ -e "$USER_DATA/stats.log" ]; then
|
||||
echo -e "$(date "+%F %T") stats.log" | tee -a $BACKUP/$user.log
|
||||
cp -r $USER_DATA/stats.log $tmpdir/hestia/
|
||||
fi
|
||||
|
||||
if [ -e "$USER_DATA/history.log" ]; then
|
||||
echo -e "$(date "+%F %T") history.log" | tee -a $BACKUP/$user.log
|
||||
cp -r $USER_DATA/history.log $tmpdir/hestia/
|
||||
fi
|
||||
|
||||
if [ -e "$USER_DATA/backup-excludes.conf" ]; then
|
||||
echo -e "$(date "+%F %T") backup-excludes.conf" | tee -a $BACKUP/$user.log
|
||||
cp -r $USER_DATA/backup-excludes.conf $tmpdir/hestia/
|
||||
fi
|
||||
|
||||
# Backup PAM
|
||||
mkdir $tmpdir/pam
|
||||
echo -e "$(date "+%F %T") pam" | tee -a $BACKUP/$user.log
|
||||
grep "^$user:" /etc/passwd > $tmpdir/pam/passwd
|
||||
grep "^$user:" /etc/shadow > $tmpdir/pam/shadow
|
||||
grep "^$user:" /etc/group > $tmpdir/pam/group
|
||||
echo
|
||||
|
||||
# Parsing excludes
|
||||
if [ -e "$USER_DATA/backup-excludes.conf" ]; then
|
||||
source $USER_DATA/backup-excludes.conf
|
||||
fi
|
||||
|
||||
# WEB domains
|
||||
if [ -n "$WEB_SYSTEM" ] && [ "$WEB" != '*' ]; then
|
||||
echo -e "\n-- WEB --" | tee -a $BACKUP/$user.log
|
||||
mkdir $tmpdir/web/
|
||||
|
||||
# Parsing domain exclusions
|
||||
conf="$USER_DATA/web.conf"
|
||||
for domain in $(search_objects 'web' 'SUSPENDED' "*" 'DOMAIN'); do
|
||||
exclusion=$(echo -e "$WEB" | tr ',' '\n' | grep "^$domain$\|^\*$")
|
||||
if [ -z "$exclusion" ]; then
|
||||
web_list="$web_list $domain"
|
||||
else
|
||||
echo "$(date "+%F %T") excluding $domain" | tee -a $BACKUP/$user.log
|
||||
fi
|
||||
done
|
||||
web_list=$(echo "$web_list" | sed -e "s/ */\ /g" -e "s/^ //")
|
||||
|
||||
i=0
|
||||
|
||||
for domain in $web_list; do
|
||||
check_backup_conditions
|
||||
((i++))
|
||||
echo -e "$(date "+%F %T") $domain" | tee -a $BACKUP/$user.log
|
||||
mkdir -p $tmpdir/web/$domain/conf
|
||||
mkdir -p $tmpdir/web/$domain/hestia
|
||||
|
||||
# Get domain variables
|
||||
domain_idn=$domain
|
||||
format_domain_idn
|
||||
get_domain_values 'web'
|
||||
|
||||
# Backup web.conf
|
||||
cd $tmpdir/web/$domain/
|
||||
conf="$USER_DATA/web.conf"
|
||||
grep "DOMAIN='$domain'" $conf > hestia/web.conf
|
||||
|
||||
# Backup vhost config
|
||||
if [ -e "$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.conf" ]; then
|
||||
cp $HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.conf* conf/
|
||||
elif [ -e "$HOMEDIR/$user/conf/web/$domain.$WEB_SYSTEM.conf" ]; then
|
||||
cp $HOMEDIR/$user/conf/web/$domain.$WEB_SYSTEM.conf* conf/
|
||||
else
|
||||
# legacy format: all domain configs in single file
|
||||
tpl_file="$WEBTPL/$WEB_SYSTEM/$WEB_BACKEND/$TPL.tpl"
|
||||
conf="$HOMEDIR/$user/conf/web/$WEB_SYSTEM.conf"
|
||||
get_web_config_lines "$tpl_file" "$conf"
|
||||
sed -n "$top_line,$bottom_line p" $conf > conf/$WEB_SYSTEM.conf
|
||||
fi
|
||||
|
||||
# Backup ssl vhost
|
||||
if [ "$SSL" = 'yes' ]; then
|
||||
if [ -e "$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.ssl.conf" ]; then
|
||||
cp $HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.ssl.conf* conf/
|
||||
elif [ -e "$HOMEDIR/$user/conf/web/$domain.$WEB_SYSTEM.ssl.conf" ]; then
|
||||
cp $HOMEDIR/$user/conf/web/$domain.$WEB_SYSTEM.ssl.conf* conf/
|
||||
else
|
||||
# legacy format: all domain configs in single file
|
||||
tpl_file="$WEBTPL/$WEB_SYSTEM/$WEB_BACKEND/$TPL.stpl"
|
||||
conf="$HOMEDIR/$user/conf/web/s$WEB_SYSTEM.conf"
|
||||
get_web_config_lines "$tpl_file" "$conf"
|
||||
sed -n "$top_line,$bottom_line p" $conf > conf/s$WEB_SYSTEM.conf
|
||||
fi
|
||||
fi
|
||||
|
||||
# Backup proxy config
|
||||
if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ]; then
|
||||
if [ -e "$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.conf" ]; then
|
||||
cp $HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.conf* conf/
|
||||
elif [ -e "$HOMEDIR/$user/conf/web/$domain.$PROXY_SYSTEM.conf" ]; then
|
||||
cp $HOMEDIR/$user/conf/web/$domain.$PROXY_SYSTEM.conf* conf/
|
||||
else
|
||||
# legacy format: all domain configs in single file
|
||||
tpl_file="$WEBTPL/$PROXY_SYSTEM/$PROXY.tpl"
|
||||
conf="$HOMEDIR/$user/conf/web/$PROXY_SYSTEM.conf"
|
||||
get_web_config_lines "$tpl_file" "$conf"
|
||||
sed -n "$top_line,$bottom_line p" $conf > conf/$PROXY_SYSTEM.conf
|
||||
fi
|
||||
fi
|
||||
|
||||
# Backup ssl proxy config
|
||||
if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ] && [ "$SSL" = 'yes' ]; then
|
||||
if [ -e "$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.ssl.conf" ]; then
|
||||
cp $HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.ssl.conf* conf/
|
||||
elif [ -e "$HOMEDIR/$user/conf/web/$domain.$PROXY_SYSTEM.ssl.conf" ]; then
|
||||
cp $HOMEDIR/$user/conf/web/$domain.$PROXY_SYSTEM.ssl.conf* conf/
|
||||
else
|
||||
# legacy format: all domain configs in single file
|
||||
tpl_file="$WEBTPL/$PROXY_SYSTEM/$PROXY.stpl"
|
||||
conf="$HOMEDIR/$user/conf/web/s$PROXY_SYSTEM.conf"
|
||||
get_web_config_lines "$tpl_file" "$conf"
|
||||
sed -n "$top_line,$bottom_line p" $conf > conf/s$PROXY_SYSTEM.conf
|
||||
fi
|
||||
fi
|
||||
|
||||
domain_conf=$(grep "DOMAIN='$domain'" $conf)
|
||||
parse_object_kv_list_non_eval domain_conf
|
||||
|
||||
mkdir -p template/$WEB_SYSTEM/
|
||||
mkdir template/php-fpm/
|
||||
|
||||
if [ $WEB_BACKEND == 'php-fpm' ]; then
|
||||
cp $HESTIA/data/templates/web/$WEB_SYSTEM/php-fpm/$TPL.tpl template/$WEB_SYSTEM/
|
||||
cp $HESTIA/data/templates/web/$WEB_SYSTEM/php-fpm/$TPL.stpl template/$WEB_SYSTEM/
|
||||
cp $HESTIA/data/templates/web/php-fpm/$BACKEND.tpl template/php-fpm/
|
||||
else
|
||||
cp $HESTIA/data/templates/web/$WEB_SYSTEM/$TPL.tpl template/$WEB_SYSTEM/
|
||||
cp $HESTIA/data/templates/web/$WEB_SYSTEM/$TPL.stpl template/$WEB_SYSTEM/
|
||||
fi
|
||||
if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ]; then
|
||||
mkdir template/$PROXY_SYSTEM
|
||||
cp $HESTIA/data/templates/web/$PROXY_SYSTEM/$PROXY.tpl template/$PROXY_SYSTEM/
|
||||
cp $HESTIA/data/templates/web/$PROXY_SYSTEM/$PROXY.stpl template/$PROXY_SYSTEM/
|
||||
fi
|
||||
|
||||
# Backup ssl certificates
|
||||
if [ "$SSL" = 'yes' ]; then
|
||||
cp $HOMEDIR/$user/conf/web/$domain/ssl/$domain.* conf/
|
||||
cp $USER_DATA/ssl/$domain.* hestia/
|
||||
fi
|
||||
|
||||
# Changin dir to documentroot
|
||||
cd $HOMEDIR/$user/web/$domain
|
||||
|
||||
# Define exclude arguments
|
||||
exclusion=$(echo -e "$WEB" | tr ',' '\n' | grep "^$domain\|\*:")
|
||||
set -f
|
||||
fargs=()
|
||||
fargs+=(--exclude='./logs/*')
|
||||
if [ -n "$exclusion" ]; then
|
||||
|
||||
if [[ "$exclusion" =~ '*' ]]; then
|
||||
exclusion="${exclusion/\*/$domain}"
|
||||
fi
|
||||
|
||||
xdirs="$(echo -e "$exclusion" | tr ':' '\n' | grep -v $domain)"
|
||||
for xpath in $xdirs; do
|
||||
if [ -d "$xpath" ]; then
|
||||
fargs+=(--exclude=$xpath/*)
|
||||
echo "$(date "+%F %T") excluding directory $xpath"
|
||||
msg="$msg\n$(date "+%F %T") excluding directory $xpath"
|
||||
else
|
||||
echo "$(date "+%F %T") excluding file $xpath"
|
||||
msg="$msg\n$(date "+%F %T") excluding file $xpath"
|
||||
fargs+=(--exclude=$xpath)
|
||||
fi
|
||||
done
|
||||
fi
|
||||
set +f
|
||||
|
||||
# Backup files
|
||||
if [ "$BACKUP_MODE" = 'zstd' ]; then
|
||||
tar "${fargs[@]}" -cpf- * | pzstd -"$BACKUP_GZIP" - > $tmpdir/web/$domain/domain_data.tar.zst
|
||||
else
|
||||
tar "${fargs[@]}" -cpf- * | gzip -"$BACKUP_GZIP" - > $tmpdir/web/$domain/domain_data.tar.gz
|
||||
fi
|
||||
done
|
||||
|
||||
# Print total
|
||||
if [ "$i" -eq 1 ]; then
|
||||
echo -e "$(date "+%F %T") *** $i domain ***" | tee -a $BACKUP/$user.log
|
||||
else
|
||||
echo -e "$(date "+%F %T") *** $i domains ***" | tee -a $BACKUP/$user.log
|
||||
fi
|
||||
fi
|
||||
|
||||
# DNS domains
|
||||
if [ -n "$DNS_SYSTEM" ] && [ "$DNS" != '*' ]; then
|
||||
echo -e "\n-- DNS --" | tee -a $BACKUP/$user.log
|
||||
mkdir $tmpdir/dns/
|
||||
|
||||
# Parsing domain exclusions
|
||||
for domain in $(search_objects 'dns' 'SUSPENDED' "*" 'DOMAIN'); do
|
||||
exclusion=$(echo "$DNS" | tr ',' '\n' | grep "^$domain$")
|
||||
if [ -z "$exclusion" ]; then
|
||||
dns_list="$dns_list $domain"
|
||||
else
|
||||
echo "$(date "+%F %T") excluding $domain"
|
||||
msg="$msg\n$(date "+%F %T") excluding $domain"
|
||||
fi
|
||||
done
|
||||
dns_list=$(echo "$dns_list" | sed -e "s/ */\ /g" -e "s/^ //")
|
||||
|
||||
i=0
|
||||
for domain in $dns_list; do
|
||||
((i++))
|
||||
echo -e "$(date "+%F %T") $domain" | tee -a $BACKUP/$user.log
|
||||
domain_idn="$domain"
|
||||
# Building directory tree
|
||||
mkdir -p $tmpdir/dns/$domain/conf
|
||||
mkdir -p $tmpdir/dns/$domain/conf/keys
|
||||
mkdir -p $tmpdir/dns/$domain/hestia
|
||||
|
||||
# Backup dns.conf
|
||||
cd $tmpdir/dns/$domain/
|
||||
conf="$USER_DATA/dns.conf"
|
||||
grep "DOMAIN='$domain'" $conf > hestia/dns.conf
|
||||
|
||||
# Backup dns recods
|
||||
cp $USER_DATA/dns/$domain.conf hestia/$domain.conf
|
||||
if [ "$DNS_SYSTEM" != 'remote' ]; then
|
||||
cp $HOMEDIR/$user/conf/dns/$domain.db conf/$domain.db
|
||||
fi
|
||||
# Backup DNSSEC public and private key if enabled
|
||||
dnssec=$(grep "DOMAIN='$domain'" $USER_DATA/dns.conf | grep "DNSSEC='yes'")
|
||||
if [ -n "$dnssec" ]; then
|
||||
format_domain_idn
|
||||
cp $USER_DATA/keys/K$domain_idn*.* $tmpdir/dns/$domain/conf/keys
|
||||
fi
|
||||
done
|
||||
|
||||
# Print total
|
||||
if [ "$i" -eq 1 ]; then
|
||||
echo -e "$(date "+%F %T") *** $i domain ***" | tee -a $BACKUP/$user.log
|
||||
else
|
||||
echo -e "$(date "+%F %T") *** $i domains ***" | tee -a $BACKUP/$user.log
|
||||
fi
|
||||
fi
|
||||
|
||||
# Mail domains
|
||||
if [ -n "$MAIL_SYSTEM" ] && [ "$MAIL" != '*' ]; then
|
||||
echo -e "\n-- MAIL --" | tee -a $BACKUP/$user.log
|
||||
mkdir $tmpdir/mail/
|
||||
|
||||
# Parsing domain exclusions
|
||||
conf="$USER_DATA/mail.conf"
|
||||
for domain in $(search_objects 'mail' 'SUSPENDED' "*" 'DOMAIN'); do
|
||||
check_exl=$(echo "$MAIL" | tr ',' '\n' | grep "^$domain$")
|
||||
if [ -z "$check_exl" ]; then
|
||||
mail_list="$mail_list $domain"
|
||||
else
|
||||
echo "$(date "+%F %T") excluding $domain" | tee -a $BACKUP/$user.log
|
||||
fi
|
||||
done
|
||||
mail_list=$(echo "$mail_list" | sed -e "s/ */\ /g" -e "s/^ //")
|
||||
|
||||
i=0
|
||||
for domain in $mail_list; do
|
||||
check_backup_conditions
|
||||
((i++))
|
||||
echo -e "$(date "+%F %T") $domain" | tee -a $BACKUP/$user.log
|
||||
mkdir -p $tmpdir/mail/$domain/conf
|
||||
mkdir -p $tmpdir/mail/$domain/hestia
|
||||
domain_idn=$domain
|
||||
format_domain_idn
|
||||
|
||||
# Backup exim config
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
cd $tmpdir/mail/$domain/
|
||||
cp -r $HOMEDIR/$user/conf/mail/$domain/* conf/
|
||||
fi
|
||||
|
||||
# Backup mail.conf
|
||||
conf="$USER_DATA/mail.conf"
|
||||
grep "DOMAIN='$domain'" $conf > hestia/mail.conf
|
||||
cp $USER_DATA/mail/$domain.* hestia/
|
||||
if [ -n "$(ls $USER_DATA/mail/ | grep *@$domain)" ]; then
|
||||
cp $USER_DATA/mail/*@$domain.* hestia/
|
||||
fi
|
||||
|
||||
# Backup emails
|
||||
cd $HOMEDIR/$user/mail/$domain_idn
|
||||
accounts=()
|
||||
for account in *; do
|
||||
exclusion=$(echo "$MAIL" | tr ',' '\n' | grep "$domain:")
|
||||
exclusion=$(echo "$exclusion" | tr ':' '\n' | grep -E "^$account|\*")
|
||||
|
||||
# Checking exclusions
|
||||
if [ -z "$exclusion" ] && [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
accounts+=($account)
|
||||
else
|
||||
echo "$(date "+%F %T") excluding mail account $account" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
fi
|
||||
done
|
||||
# Compress archive
|
||||
if [ ${#accounts[@]} -gt 0 ]; then
|
||||
if [ "$BACKUP_MODE" = 'zstd' ]; then
|
||||
tar -cpf- "${accounts[@]}" | pzstd -"$BACKUP_GZIP" - > $tmpdir/mail/$domain/accounts.tar.zst
|
||||
else
|
||||
tar -cpf- "${accounts[@]}" | gzip -"$BACKUP_GZIP" - > $tmpdir/mail/$domain/accounts.tar.gz
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Print total
|
||||
if [ "$i" -eq 1 ]; then
|
||||
echo -e "$(date "+%F %T") *** $i domain ***" | tee -a $BACKUP/$user.log
|
||||
else
|
||||
echo -e "$(date "+%F %T") *** $i domains ***" | tee -a $BACKUP/$user.log
|
||||
fi
|
||||
fi
|
||||
|
||||
# Databases
|
||||
if [ -n "$DB_SYSTEM" ] && [ "$DB" != '*' ]; then
|
||||
echo -e "\n-- DB --" | tee -a $BACKUP/$user.log
|
||||
mkdir $tmpdir/db/
|
||||
|
||||
# Parsing database exclusions
|
||||
for database in $(search_objects 'db' 'SUSPENDED' "*" 'DB'); do
|
||||
exclusion=$(echo "$DB" | tr ',' '\n' | grep "^$database$")
|
||||
if [ -z "$exclusion" ]; then
|
||||
db_list="$db_list $database"
|
||||
else
|
||||
echo "$(date "+%F %T") excluding $database" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
fi
|
||||
done
|
||||
|
||||
i=0
|
||||
conf="$USER_DATA/db.conf"
|
||||
db_list=$(echo "$db_list" | sed -e "s/ */\ /g" -e "s/^ //")
|
||||
for database in $db_list; do
|
||||
check_backup_conditions
|
||||
((i++))
|
||||
get_database_values
|
||||
|
||||
echo -e "$(date "+%F %T") $database ($TYPE)" | tee -a $BACKUP/$user.log
|
||||
mkdir -p $tmpdir/db/$database/conf
|
||||
mkdir -p $tmpdir/db/$database/hestia
|
||||
|
||||
cd $tmpdir/db/$database/
|
||||
grep "DB='$database'" $conf > hestia/db.conf
|
||||
|
||||
dump="$tmpdir/db/$database/$database.$TYPE.sql"
|
||||
if [ "$BACKUP_MODE" = 'zstd' ]; then
|
||||
dumpgz="$tmpdir/db/$database/$database.$TYPE.sql.zst"
|
||||
else
|
||||
dumpgz="$tmpdir/db/$database/$database.$TYPE.sql.gz"
|
||||
fi
|
||||
|
||||
grants="$tmpdir/db/$database/conf/$database.$TYPE.$DBUSER"
|
||||
if [ ! -f "$dumpgz" ]; then
|
||||
|
||||
WAIT_LOOP_ENTERED=0
|
||||
while true; do
|
||||
if pgrep -x "mysqldump" > /dev/null; then
|
||||
WAIT_LOOP_ENTERED=1
|
||||
echo "Wait other mysqldump to finish"
|
||||
sleep 1
|
||||
else
|
||||
if [ "$WAIT_LOOP_ENTERED" -eq 1 ]; then
|
||||
echo "We can use mysqldump now"
|
||||
fi
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
case $TYPE in
|
||||
mysql) dump_mysql_database ;;
|
||||
pgsql) dump_pgsql_database ;;
|
||||
esac
|
||||
|
||||
# Compress dump
|
||||
if [ "$BACKUP_MODE" = 'zstd' ]; then
|
||||
pzstd -$BACKUP_GZIP $dump
|
||||
rm $dump
|
||||
else
|
||||
gzip -$BACKUP_GZIP $dump
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Print total
|
||||
if [ "$i" -eq 1 ]; then
|
||||
echo -e "$(date "+%F %T") *** $i database ***" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
else
|
||||
echo -e "$(date "+%F %T") *** $i databases ***" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
fi
|
||||
fi
|
||||
|
||||
# Cron jobs
|
||||
if [ -n "$CRON_SYSTEM" ] && [ "$CRON" != '*' ]; then
|
||||
echo -e "\n-- CRON --" | tee -a $BACKUP/$user.log
|
||||
mkdir $tmpdir/cron/
|
||||
|
||||
# Backup cron.conf
|
||||
cp $USER_DATA/cron.conf $tmpdir/cron/
|
||||
cron_record=$(wc -l $USER_DATA/cron.conf | cut -f 1 -d ' ')
|
||||
|
||||
if [ -e "/var/spool/cron/$user" ]; then
|
||||
cron_list="$cron_record"
|
||||
cp /var/spool/cron/$user $tmpdir/cron/
|
||||
fi
|
||||
|
||||
# Print total
|
||||
if [ "$cron_record" -eq 1 ]; then
|
||||
echo -e "$(date "+%F %T") *** $cron_record job ***" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
else
|
||||
echo -e "$(date "+%F %T") *** $cron_record jobs ***" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
fi
|
||||
fi
|
||||
|
||||
# User Directories
|
||||
if [ "$USER" != '*' ]; then
|
||||
echo -e "\n-- User Dir --" | tee -a $BACKUP/$user.log
|
||||
mkdir $tmpdir/user_dir
|
||||
cd $HOMEDIR/$user
|
||||
|
||||
# Parsing directory exclusions
|
||||
USER=''
|
||||
if [ -e "$USER_DATA/backup-excludes.conf" ]; then
|
||||
source $USER_DATA/backup-excludes.conf
|
||||
fi
|
||||
fargs=()
|
||||
for xpath in $(echo "$USER" | tr ',' '\n'); do
|
||||
if [ -d "$xpath" ]; then
|
||||
fargs+=(--exclude="$xpath"/*)
|
||||
echo "$(date "+%F %T") excluding directory $xpath" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
else
|
||||
echo "$(date "+%F %T") excluding file $xpath" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
fargs+=(--exclude="$xpath")
|
||||
fi
|
||||
done
|
||||
|
||||
IFS=$'\n'
|
||||
set -f
|
||||
i=0
|
||||
|
||||
for udir in $(ls -a | egrep -v "^conf$|^web$|^dns$|^tmp$|^mail$|^\.\.$|^\.$"); do
|
||||
exclusion=$(echo "$USER" | tr ',' '\n' | grep "^$udir$")
|
||||
if [ -z "$exclusion" ]; then
|
||||
((i++))
|
||||
udir_list="$udir_list $udir"
|
||||
echo -e "$(date "+%F %T") adding $udir" | tee -a $BACKUP/$user.log
|
||||
|
||||
check_backup_conditions
|
||||
|
||||
# Backup files and dirs
|
||||
if [ "$BACKUP_MODE" = 'zstd' ]; then
|
||||
tar --anchored -cpf- "${fargs[@]}" $udir | pzstd -"$BACKUP_GZIP" - > $tmpdir/user_dir/$udir.tar.zst
|
||||
else
|
||||
tar --anchored -cpf- "${fargs[@]}" $udir | gzip -"$BACKUP_GZIP" - > $tmpdir/user_dir/$udir.tar.gz
|
||||
fi
|
||||
|
||||
fi
|
||||
done
|
||||
set +f
|
||||
udir_list=$(echo "$udir_list" | sed -e "s/ */\ /g" -e "s/^ //")
|
||||
|
||||
# Print total
|
||||
if [ "$i" -eq 1 ]; then
|
||||
echo -e "$(date "+%F %T") *** $i user directory ***" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
else
|
||||
echo -e "$(date "+%F %T") *** $i directories ***" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$BACKUP_MODE" = 'zstd' ]; then
|
||||
touch $tmpdir/.zstd
|
||||
fi
|
||||
|
||||
# Get backup size
|
||||
size="$(du -shm $tmpdir | cut -f 1)"
|
||||
|
||||
# Get current time
|
||||
end_time=$(date '+%s')
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
backup_new_date=$(date +"%Y-%m-%d_%H-%M-%S")
|
||||
|
||||
echo -e "\n-- SUMMARY --" | tee -a $BACKUP/$user.log
|
||||
|
||||
errorcode="0"
|
||||
# Switching on backup system types
|
||||
for backup_type in $(echo -e "${BACKUP_SYSTEM//,/\\n}"); do
|
||||
case $backup_type in
|
||||
local) local_backup ;;
|
||||
ftp) ftp_backup ;;
|
||||
sftp) sftp_backup ;;
|
||||
b2) b2_backup ;;
|
||||
rclone) rclone_backup ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Removing tmpdir
|
||||
rm -rf $tmpdir
|
||||
if [[ "$errorcode" != "0" ]]; then
|
||||
if [[ "$BACKUP_SYSTEM" =~ "local" ]]; then
|
||||
echo -e "$(date "+%F %T") *** Local backup was successfully executed. Remote backup failed ***" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
BACKUP_SYSTEM="local"
|
||||
else
|
||||
echo -e "$(date "+%F %T") *** Remote backup failed ***" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
|
||||
exit $error_code
|
||||
fi
|
||||
fi
|
||||
# Calculation run time
|
||||
run_time=$((end_time - start_time))
|
||||
run_time=$((run_time / 60))
|
||||
current_time=$(date "+%T")
|
||||
if [ "$run_time" -lt 1 ]; then
|
||||
run_time=1
|
||||
fi
|
||||
min=minutes
|
||||
if [ "$run_time" -eq 1 ]; then
|
||||
min=minute
|
||||
fi
|
||||
|
||||
echo "$(date "+%F %T") Size: $size MB" | tee -a $BACKUP/$user.log
|
||||
echo "$(date "+%F %T") Runtime: $run_time $min" | tee -a $BACKUP/$user.log
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Removing duplicate
|
||||
touch $USER_DATA/backup.conf
|
||||
sed -i "/$user.$backup_new_date.tar/d" $USER_DATA/backup.conf
|
||||
|
||||
# Registering new backup
|
||||
backup_str="BACKUP='$user.$backup_new_date.tar'"
|
||||
backup_str="$backup_str TYPE='$BACKUP_SYSTEM' SIZE='$size'"
|
||||
backup_str="$backup_str WEB='${web_list// /,}'"
|
||||
backup_str="$backup_str DNS='${dns_list// /,}'"
|
||||
backup_str="$backup_str MAIL='${mail_list// /,}'"
|
||||
backup_str="$backup_str DB='${db_list// /,}'"
|
||||
backup_str="$backup_str CRON='$cron_list'"
|
||||
backup_str="$backup_str UDIR='${udir_list// /,}'"
|
||||
backup_str="$backup_str RUNTIME='$run_time' TIME='$time' DATE='$date'"
|
||||
echo "$backup_str" >> $USER_DATA/backup.conf
|
||||
|
||||
# Removing old backups
|
||||
tail -n $BACKUPS $USER_DATA/backup.conf > $USER_DATA/backup.conf_
|
||||
mv -f $USER_DATA/backup.conf_ $USER_DATA/backup.conf
|
||||
chmod 660 $USER_DATA/backup.conf
|
||||
chmod 660 $BACKUP/$user.log
|
||||
|
||||
# Deleting task from queue
|
||||
sed -i "/v-backup-user $user /d" $HESTIA/data/queue/backup.pipe
|
||||
|
||||
U_BACKUPS=$(grep BACKUP $USER_DATA/backup.conf | wc -l)
|
||||
update_user_value "$user" '$U_BACKUPS' "$U_BACKUPS"
|
||||
cd $BACKUP
|
||||
|
||||
# Send notification
|
||||
if [ -e "$BACKUP/$user.log" ] && [ "$notify" = "yes" ]; then
|
||||
subj="$user → backup has been completed"
|
||||
email=$(get_user_value '$CONTACT')
|
||||
cat $BACKUP/$user.log | $SENDMAIL -s "$subj" "$email" "$notify"
|
||||
$BIN/v-add-user-notification "$user" "Backup created successfully" "<p><span class='u-text-bold'>Archive:</span> <code>$user.$backup_new_date.tar</code></p>"
|
||||
fi
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Backup" "Backup created (Archive: $backup_new_date.tar)."
|
||||
$BIN/v-log-action "system" "Info" "Backup" "Backup created (User: $user, Archive: $backup_new_date.tar)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,56 @@
|
||||
#!/bin/bash
|
||||
# info: backup all users
|
||||
# options: NONE
|
||||
#
|
||||
# example: v-backup-users
|
||||
#
|
||||
# This function backups all system users.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Auto-repair all databases before backuping all accounts
|
||||
mysqlrepair --all-databases --check --auto-repair > /dev/null 2>&1
|
||||
|
||||
if [ -z "$BACKUP_SYSTEM" ]; then
|
||||
exit
|
||||
fi
|
||||
for user in $($BIN/v-list-sys-users plain); do
|
||||
check_suspend=$(grep "SUSPENDED='no'" $HESTIA/data/users/$user/user.conf)
|
||||
log=$HESTIA/log/backup.log
|
||||
if [ ! -f "$HESTIA/data/users/$user/user.conf" ]; then
|
||||
continue
|
||||
fi
|
||||
check_backup_conditions
|
||||
check_suspend=$(grep "SUSPENDED='no'" $HESTIA/data/users/$user/user.conf)
|
||||
log=$HESTIA/log/backup.log
|
||||
if [ -n "$check_suspend" ]; then
|
||||
echo -e "================================" >> $log
|
||||
echo -e "$user" >> $log
|
||||
echo -e "--------------------------------\n" >> $log
|
||||
nice -n 19 ionice -c2 -n7 $BIN/v-backup-user $user >> $log 2>&1
|
||||
echo -e "\n--------------------------------\n\n" >> $log
|
||||
fi
|
||||
done
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
exit
|
@ -0,0 +1,85 @@
|
||||
#!/bin/bash
|
||||
# info: change cron job
|
||||
# options: USER JOB MIN HOUR DAY MONTH WDAY COMMAND
|
||||
#
|
||||
# example: v-change-cron-job admin 7 * * * * * * /usr/bin/uptime
|
||||
#
|
||||
# This function is used for changing existing job. It fully replace job
|
||||
# parameters with new one but with same id.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
job=$2
|
||||
min=$3
|
||||
hour=$4
|
||||
day=$5
|
||||
month=$6
|
||||
wday=$7
|
||||
command=$8
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '7' "$#" 'USER JOB MIN HOUR DAY MONTH WDAY COMMAND'
|
||||
is_format_valid 'user' 'job' 'min' 'hour' 'day' 'month' 'wday' 'command'
|
||||
is_system_enabled "$CRON_SYSTEM" 'CRON_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'cron' 'JOB' "$job"
|
||||
is_object_unsuspended 'cron' 'JOB' "$job"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Concatenating cron string
|
||||
command=$(echo $command | sed -e "s/'/%quote%/g")
|
||||
str="JOB='$job' MIN='$min' HOUR='$hour' DAY='$day' MONTH='$month' WDAY='$wday'"
|
||||
str="$str CMD='$command' SUSPENDED='no' TIME='$time' DATE='$date'"
|
||||
|
||||
# Deleting old job
|
||||
sed -i "/JOB='$job' /d" $USER_DATA/cron.conf
|
||||
|
||||
# Adding new
|
||||
echo "$str" >> $USER_DATA/cron.conf
|
||||
|
||||
# Sorting jobs by id
|
||||
sort_cron_jobs
|
||||
|
||||
# Sync system cron with user
|
||||
sync_cron_jobs
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Restarting crond
|
||||
$BIN/v-restart-cron
|
||||
check_result $? "Cron restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Cron Jobs" "Cron job updated (Job: $job, Command: $command)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,78 @@
|
||||
#!/bin/bash
|
||||
# info: change database server password
|
||||
# options: TYPE HOST USER PASSWORD
|
||||
#
|
||||
# example: v-change-database-host-password mysql localhost wp_user pA$$w@rD
|
||||
#
|
||||
# This function changes database server password.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
type=$1
|
||||
host=$2
|
||||
dbuser=$3
|
||||
password=$4
|
||||
HIDE=4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/db.sh
|
||||
source $HESTIA/func/db.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
args_usage='TYPE HOST DBUSER DBPASS'
|
||||
check_args '4' "$#" "$args_usage"
|
||||
is_format_valid 'host' 'dbuser'
|
||||
is_object_valid "../../conf/$type" 'HOST' "$host"
|
||||
dbpass="$password"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Define email
|
||||
email=$(grep CONTACT $HESTIA/data/users/admin/user.conf | cut -f2 -d \')
|
||||
subj="v-change-database-host-password $*"
|
||||
|
||||
case $type in
|
||||
mysql)
|
||||
mysql_connect "$host"
|
||||
query="USE mysql; UPDATE user SET"
|
||||
query="$query password=PASSWORD('$dbpass')"
|
||||
query="$query WHERE User='$dbuser';"
|
||||
query="$query FLUSH PRIVILEGES;"
|
||||
mysql_query "$query"
|
||||
if [ "$dbuser" == "root" ]; then
|
||||
echo -e "[client]\npassword='$dbpass'\n" > /root/.my.cnf
|
||||
chmod 600 /root/.my.cnf
|
||||
fi
|
||||
;;
|
||||
pgsql) echo "TBD" > /dev/null ;;
|
||||
esac
|
||||
|
||||
update_object_value "../../conf/$type" 'HOST' "$host" '$USER' "$dbuser"
|
||||
update_object_value "../../conf/$type" 'HOST' "$host" '$PASSWORD' "$dbpass"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Warning" "Database" "Password changed for remote database host (Host: $host)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,133 @@
|
||||
#!/bin/bash
|
||||
# info: change database owner
|
||||
# options: DATABASE USER
|
||||
#
|
||||
# example: v-change-database-owner mydb alice
|
||||
#
|
||||
# This function for changing database owner.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
database=$1
|
||||
user=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/db.sh
|
||||
source $HESTIA/func/db.sh
|
||||
# shellcheck source=/usr/local/hestia/func/rebuild.sh
|
||||
source $HESTIA/func/rebuild.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'DATABASE USER'
|
||||
is_format_valid 'database' 'user'
|
||||
is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
|
||||
# Check owner existence
|
||||
owner=$(echo $database | cut -f 1 -d '_')
|
||||
if [ ! -d "$HESTIA/data/users/$owner" ]; then
|
||||
echo "Error: database owner doesn't exist"
|
||||
log_event "$E_NOTEXIST" "$ARGUMENTS"
|
||||
exit "$E_NOTEXIST"
|
||||
fi
|
||||
|
||||
# Check if owner is the same as the dst user
|
||||
if [ "$owner" = "$user" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Check db existence
|
||||
db_data=$(grep "DB='$database'" $HESTIA/data/users/$owner/db.conf)
|
||||
if [ -z "$db_data" ]; then
|
||||
echo "Error: database $database doesn't exist"
|
||||
log_event "$E_NOTEXIST" "$ARGUMENTS"
|
||||
exit "$E_NOTEXIST"
|
||||
fi
|
||||
|
||||
parse_object_kv_list "$db_data"
|
||||
#Fix issue #1084 with "Upper case not allowed with PGSQL"
|
||||
if [ "$TYPE" == "pgsql" ]; then
|
||||
usersmall=$(echo "$user" | tr '[:upper:]' '[:lower:]')
|
||||
else
|
||||
usersmall=$user
|
||||
fi
|
||||
|
||||
# Check if database name is uniqe
|
||||
new_db=$(echo $database | sed "s/^${owner}_/${usersmall}_/")
|
||||
check_db=$(grep "DB='$new_db'" $HESTIA/data/users/$user/db.conf)
|
||||
if [ -n "$check_db" ]; then
|
||||
echo "Error: $new_db database exists"
|
||||
log_event "$E_EXISTS" "$ARGUMENTS"
|
||||
exit "$E_EXISTS"
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Creating temporary directory
|
||||
tmpdir=$(mktemp -p $BACKUP -d "tmp.$database.XXXXXXXXXX")
|
||||
|
||||
# Suspend database
|
||||
$BIN/v-suspend-database $owner $database > /dev/null 2>&1
|
||||
|
||||
# Dump database
|
||||
dump="$tmpdir/$database.$TYPE.sql"
|
||||
grants="$tmpdir/$database.$TYPE.$DBUSER"
|
||||
case $TYPE in
|
||||
mysql) dump_mysql_database ;;
|
||||
pgsql) dump_pgsql_database ;;
|
||||
esac
|
||||
|
||||
# Import configuration
|
||||
db_data=$(echo "$db_data" | sed "s/'${owner}_/'${usersmall}_/g")
|
||||
echo "$db_data" >> $HESTIA/data/users/$user/db.conf
|
||||
parse_object_kv_list "$db_data"
|
||||
|
||||
# Unsuspend db
|
||||
$BIN/v-unsuspend-database "$user" "$new_db" > /dev/null 2>&1
|
||||
|
||||
# Rebuild databases
|
||||
$BIN/v-rebuild-databases "$user"
|
||||
|
||||
# Import dump
|
||||
case $TYPE in
|
||||
mysql) import_mysql_database "$dump" ;;
|
||||
pgsql) import_pgsql_database "$dump" ;;
|
||||
esac
|
||||
|
||||
# Deleting tmpdir
|
||||
rm -rf $tmpdir
|
||||
|
||||
# Remove old database
|
||||
$BIN/v-unsuspend-database "$owner" "$database" > /dev/null 2>&1
|
||||
$BIN/v-delete-database "$owner" "$database" > /dev/null 2>&1
|
||||
|
||||
# Update counters
|
||||
$BIN/v-update-user-counters "$owner"
|
||||
$BIN/v-update-user-counters "$user"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,69 @@
|
||||
#!/bin/bash
|
||||
# info: change database password
|
||||
# options: USER DATABASE DBPASS
|
||||
#
|
||||
# example: v-change-database-password admin wp_db neW_pAssWorD
|
||||
#
|
||||
# This function for changing database user password to a database. It uses the
|
||||
# full name of database as argument.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
database=$2
|
||||
password=$3
|
||||
HIDE=3
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/db.sh
|
||||
source $HESTIA/func/db.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DATABASE DBPASS'
|
||||
is_format_valid 'user' 'database'
|
||||
is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'db' 'DB' "$database"
|
||||
is_object_unsuspended 'db' 'DB' "$database"
|
||||
is_password_valid
|
||||
dbpass="$password"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
# Get database values
|
||||
get_database_values
|
||||
|
||||
case $TYPE in
|
||||
mysql) change_mysql_password ;;
|
||||
pgsql) change_pgsql_password ;;
|
||||
esac
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Update config value
|
||||
update_object_value 'db' 'DB' "$database" '$MD5' "$md5"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Database" "Database password changed (Database: $database)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,109 @@
|
||||
#!/bin/bash
|
||||
# info: change database username
|
||||
# options: USER DATABASE DBUSER [DBPASS]
|
||||
#
|
||||
# example: v-change-database-user admin my_db joe_user
|
||||
#
|
||||
# This function for changing database user. It uses the
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
database=$2
|
||||
dbuser="$user"_"$3"
|
||||
password=$4
|
||||
HIDE=4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/db.sh
|
||||
source $HESTIA/func/db.sh
|
||||
# shellcheck source=/usr/local/hestia/func/rebuild.sh
|
||||
source $HESTIA/func/rebuild.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DATABASE DBUSER [DBPASS]'
|
||||
is_format_valid 'user' 'database' 'dbuser'
|
||||
is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'db' 'DB' "$database"
|
||||
is_object_new 'db' 'DBUSER' "$dbuser"
|
||||
is_object_unsuspended 'db' 'DB' "$database"
|
||||
is_password_valid
|
||||
dbpass="$password"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Compare old and new user
|
||||
old_dbuser=$(get_object_value 'db' 'DB' "$database" '$DBUSER')
|
||||
if [ "$old_dbuser" = "$dbuser" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Set new dbuser
|
||||
update_object_value 'db' 'DB' "$database" '$DBUSER' "$dbuser"
|
||||
|
||||
# Get database values
|
||||
get_database_values
|
||||
|
||||
#Fix issue #1084 with "Upper case not allowed with PGSQL"
|
||||
if [ "$TYPE" = "pgsql" ]; then
|
||||
dbuser=$(echo $dbuser | tr '[:upper:]' '[:lower:]')
|
||||
exclude="-"
|
||||
if [[ "$dbuser" =~ $exclude ]]; then
|
||||
check_result "$E_INVALID" "invalid database user format"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Rebuild database
|
||||
case $TYPE in
|
||||
mysql) rebuild_mysql_database ;;
|
||||
pgsql) rebuild_pgsql_database ;;
|
||||
esac
|
||||
|
||||
# Change password
|
||||
if [ -n "$dbpass" ]; then
|
||||
case $TYPE in
|
||||
mysql) change_mysql_password ;;
|
||||
pgsql) change_pgsql_password ;;
|
||||
esac
|
||||
|
||||
# Update config value
|
||||
update_object_value 'db' 'DB' "$database" '$MD5' "$md5"
|
||||
fi
|
||||
|
||||
# Remove old user
|
||||
check_old_dbuser=$(grep "DBUSER='$old_dbuser'" $USER_DATA/db.conf)
|
||||
if [ -z "$check_old_dbuser" ]; then
|
||||
case $TYPE in
|
||||
mysql) delete_mysql_user ;;
|
||||
pgsql) delete_pgsql_user ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Database" "Database user changed (Database: $database, User: $dbuser)"
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,107 @@
|
||||
#!/bin/bash
|
||||
# info: change dns domain dnssec status
|
||||
# options: USER DOMAIN STATUS
|
||||
#
|
||||
# example: v-change-dns-domain-dnssec admin domain.pp.ua yes
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
status=$3
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/rebuild.sh
|
||||
source $HESTIA/func/rebuild.sh
|
||||
# shellcheck source=/usr/local/hestia/func/syshealth.sh
|
||||
source $HESTIA/func/syshealth.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN STATUS'
|
||||
is_format_valid 'user' 'domain' ''
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'dns' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'dns' 'DOMAIN' "$domain"
|
||||
|
||||
if [ -n "$status" ]; then
|
||||
is_boolean_format_valid "$status" 'status'
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
if [ "$DNS_CLUSTER_SYSTEM" != 'hestia-zone' ]; then
|
||||
check_result "$E_DISABLED" "DNSSEC is not supported when DNS_CLUSTER_SYSTEM is not set to hestia-zone"
|
||||
fi
|
||||
|
||||
version=$(named -v | awk 'NR==1{print $2}')
|
||||
if version_ge '9.16.18' $version; then
|
||||
check_result "$E_DISABLED" "DNSSEC is not supported when bind / named version <= 9.16.18"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ -f "$HESTIA/data/queue/dns-cluster.pipe" ]; then
|
||||
bash $HESTIA/data/queue/dns-cluster.pipe
|
||||
fi
|
||||
|
||||
syshealth_repair_dns_config
|
||||
|
||||
# Changing exp
|
||||
update_object_value 'dns' 'DOMAIN' "$domain" '$DNSSEC' "$status"
|
||||
|
||||
# Update serial
|
||||
update_domain_serial
|
||||
# Rebuild DNS config
|
||||
rebuild_dns_domain_conf
|
||||
|
||||
if [ $status = "no" ]; then
|
||||
update_object_value 'dns' 'DOMAIN' "$domain" '$KEY' ""
|
||||
# Delete existing keys
|
||||
rm -fr $HOMEDIR/$user/conf/dns/$domain.db.*
|
||||
rm -fr /var/cache/bind/K$domain_idn.*
|
||||
rm -fr $USER_DATA/keys/K$domain_idn.*
|
||||
fi
|
||||
|
||||
# Updating dns-cluster queue
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
# Check for first sync
|
||||
dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe)
|
||||
if [ -z "$dlock" ]; then
|
||||
cmd="$BIN/v-add-remote-dns-domain $user $domain yes"
|
||||
echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "DNS" "Updated DNS SOA expiration date (Domain: $domain, Value: $exp)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,73 @@
|
||||
#!/bin/bash
|
||||
# info: change dns domain expiration date
|
||||
# options: USER DOMAIN EXP
|
||||
#
|
||||
# example: v-change-dns-domain-exp admin domain.pp.ua 2020-11-20
|
||||
#
|
||||
# This function of changing the term of expiration domain's registration. The
|
||||
# serial number will be refreshed automatically during update.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
exp=$3
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN EXP'
|
||||
is_format_valid 'user' 'domain' 'exp'
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'dns' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'dns' 'DOMAIN' "$domain"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Changing exp
|
||||
update_object_value 'dns' 'DOMAIN' "$domain" '$EXP' "$exp"
|
||||
|
||||
# Updating dns-cluster queue
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
# Check for first sync
|
||||
dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe)
|
||||
if [ -z "$dlock" ]; then
|
||||
cmd="$BIN/v-change-remote-dns-domain-exp $user $domain $exp"
|
||||
echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "DNS" "Updated DNS SOA expiration date (Domain: $domain, Value: $exp)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,95 @@
|
||||
#!/bin/bash
|
||||
# info: change dns domain ip address
|
||||
# options: USER DOMAIN IP [RESTART]
|
||||
#
|
||||
# example: v-change-dns-domain-ip admin domain.com 123.212.111.222
|
||||
#
|
||||
# This function for changing the main ip of DNS zone.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
ip=$3
|
||||
restart=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/rebuild.sh
|
||||
source $HESTIA/func/rebuild.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN IP [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'ip'
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'dns' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'dns' 'DOMAIN' "$domain"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Get old ip
|
||||
get_domain_values 'dns'
|
||||
old=$IP
|
||||
|
||||
# Changing ip
|
||||
update_object_value 'dns' 'DOMAIN' "$domain" '$IP' "$ip"
|
||||
|
||||
# Changing records
|
||||
sed -i "s/$old/$ip/g" $USER_DATA/dns/$domain.conf
|
||||
|
||||
# Update serial
|
||||
update_domain_serial
|
||||
# Updating zone
|
||||
if [[ "$DNS_SYSTEM" =~ named|bind ]]; then
|
||||
rebuild_dns_domain_conf
|
||||
fi
|
||||
|
||||
# Updating dns-cluster queue
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
# Check for first sync
|
||||
dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe)
|
||||
if [ -z "$dlock" ]; then
|
||||
cmd="$BIN/v-add-remote-dns-domain $user $domain yes"
|
||||
echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Restarting named
|
||||
$BIN/v-restart-dns "$restart"
|
||||
check_result $? "DNS restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "DNS" "IP address for DNS domain changed (IP: $ip, Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,89 @@
|
||||
#!/bin/bash
|
||||
# info: change dns domain soa record
|
||||
# options: USER DOMAIN SOA [RESTART]
|
||||
#
|
||||
# example: v-change-dns-domain-soa admin acme.com d.ns.domain.tld
|
||||
#
|
||||
# This function for changing SOA record. This type of records can not be
|
||||
# modified by v-change-dns-record call.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
soa=$(echo $3 | sed -e 's/\.*$//g' -e 's/^\.*//g')
|
||||
restart=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/rebuild.sh
|
||||
source $HESTIA/func/rebuild.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN SOA [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'soa'
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'dns' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'dns' 'DOMAIN' "$domain"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Changing soa
|
||||
update_object_value 'dns' 'DOMAIN' "$domain" '$SOA' "$soa"
|
||||
|
||||
# Update serial
|
||||
update_domain_serial
|
||||
# Updating zone
|
||||
if [[ "$DNS_SYSTEM" =~ named|bind ]]; then
|
||||
rebuild_dns_domain_conf
|
||||
fi
|
||||
|
||||
# Updating dns-cluster queue
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
# Check for first sync
|
||||
dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe)
|
||||
if [ -z "$dlock" ]; then
|
||||
cmd="$BIN/v-change-remote-dns-domain-soa $user $domain $soa"
|
||||
echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Restarting named
|
||||
$BIN/v-restart-dns "$restart"
|
||||
check_result $? "DNS restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "DNS" "SOA record for DNS domain changed (SOA: $soa, Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,172 @@
|
||||
#!/bin/bash
|
||||
# info: change dns domain template
|
||||
# options: USER DOMAIN TEMPLATE [RESTART]
|
||||
#
|
||||
# example: v-change-dns-domain-tpl admin example.com child-ns yes
|
||||
#
|
||||
# This function for changing the template of records. By updating old records
|
||||
# will be removed and new records will be generated in accordance with
|
||||
# parameters of new template.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
template=$3
|
||||
restart=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/rebuild.sh
|
||||
source $HESTIA/func/rebuild.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN TEMPLATE [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'template'
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'dns' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'dns' 'DOMAIN' "$domain"
|
||||
is_dns_template_valid "$template"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Defining variables
|
||||
get_domain_values 'dns'
|
||||
i=1
|
||||
ns=$(get_user_value '$NS')
|
||||
for nameserver in ${ns//,/ }; do
|
||||
eval ns$i=$nameserver
|
||||
((++i))
|
||||
done
|
||||
|
||||
# Reading template
|
||||
template_data=$(cat "$DNSTPL/$template.tpl")
|
||||
|
||||
# Deleting unused nameservers
|
||||
if [ -z "$ns3" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns3%)
|
||||
fi
|
||||
if [ -z "$ns4" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns4%)
|
||||
fi
|
||||
if [ -z "$ns5" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns5%)
|
||||
fi
|
||||
if [ -z "$ns6" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns6%)
|
||||
fi
|
||||
if [ -z "$ns7" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns7%)
|
||||
fi
|
||||
if [ -z "$ns8" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns8%)
|
||||
fi
|
||||
|
||||
# Changing tpl
|
||||
echo "$template_data" \
|
||||
| sed -e "s/%ip%/$IP/g" \
|
||||
-e "s/%domain_idn%/$domain_idn/g" \
|
||||
-e "s/%domain%/$domain/g" \
|
||||
-e "s/%ns1%/$ns1/g" \
|
||||
-e "s/%ns2%/$ns2/g" \
|
||||
-e "s/%ns3%/$ns3/g" \
|
||||
-e "s/%ns4%/$ns4/g" \
|
||||
-e "s/%ns5%/$ns5/g" \
|
||||
-e "s/%ns6%/$ns6/g" \
|
||||
-e "s/%ns7%/$ns7/g" \
|
||||
-e "s/%ns8%/$ns8/g" \
|
||||
-e "s/%time%/$TIME/g" \
|
||||
-e "s/%date%/$DATE/g" > $USER_DATA/dns/$domain.conf
|
||||
records="$(wc -l $USER_DATA/dns/$domain.conf | cut -f 1 -d ' ')"
|
||||
|
||||
# Refresh DKIM records in DNS if signing key exists for domain
|
||||
if [ "$template" = "default" ] || [ "$template" = "child-ns" ]; then
|
||||
if [ -n "$MAIL_SYSTEM" ] && [ -f "$HOMEDIR/$user/conf/mail/$domain/dkim.pem" ]; then
|
||||
check_dns_domain=$(is_object_valid 'dns' 'DOMAIN' "$domain")
|
||||
if [ "$?" -eq 0 ]; then
|
||||
p=$(cat "$USER_DATA/mail/$domain.pub" | grep -v ' KEY---' | tr -d '\n')
|
||||
record='_domainkey'
|
||||
policy="\"t=y; o=~;\""
|
||||
$BIN/v-add-dns-record "$user" "$domain" "$record" TXT "$policy" '' '' 'no'
|
||||
|
||||
record='mail._domainkey'
|
||||
selector="\"v=DKIM1\; k=rsa\; p=$p\""
|
||||
$BIN/v-add-dns-record "$user" "$domain" "$record" TXT "$selector"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Set correct domain name formatting for Office 365/Microsoft 365 MX records
|
||||
if [ "$template" = "office365" ]; then
|
||||
check_dns_domain=$(is_object_valid 'dns' 'DOMAIN' "$domain")
|
||||
if [ "$?" -eq 0 ]; then
|
||||
record='@'
|
||||
formatted_domain=$(echo "$domain" | sed 's/\./-/g')
|
||||
$BIN/v-add-dns-record "$user" "$domain" "$record" MX "${formatted_domain}.mail.protection.outlook.com." '0' '' "$restart"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Update serial
|
||||
update_domain_serial
|
||||
# Updating zone
|
||||
if [[ "$DNS_SYSTEM" =~ named|bind ]]; then
|
||||
rebuild_dns_domain_conf
|
||||
fi
|
||||
|
||||
# Updating dns-cluster queue
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
# Check for first sync
|
||||
dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe)
|
||||
if [ -z "$dlock" ]; then
|
||||
cmd="$BIN/v-add-remote-dns-domain $user $domain domain"
|
||||
echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Updating hestia config
|
||||
update_object_value 'dns' 'DOMAIN' "$domain" '$TPL' "$template"
|
||||
update_object_value 'dns' 'DOMAIN' "$domain" '$RECORDS' "$records"
|
||||
|
||||
# Rebuild DNS zone and update counters to ensure that it has updated correctly
|
||||
$BIN/v-rebuild-dns-domain "$user" "$domain" no
|
||||
$BIN/v-update-user-stats "$user"
|
||||
$BIN/v-update-user-counters "$user"
|
||||
|
||||
# Restarting named
|
||||
$BIN/v-restart-dns "$restart"
|
||||
check_result $? "DNS restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "DNS" "Template for DNS domain changed (Template: $template, Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,88 @@
|
||||
#!/bin/bash
|
||||
# info: change dns domain ttl
|
||||
# options: USER DOMAIN TTL [RESTART]
|
||||
#
|
||||
# example: v-change-dns-domain-ttl alice example.com 14400
|
||||
#
|
||||
# This function for changing the time to live TTL parameter for all records.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
ttl=$3
|
||||
restart=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/rebuild.sh
|
||||
source $HESTIA/func/rebuild.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN TTL [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'ttl'
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'dns' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'dns' 'DOMAIN' "$domain"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Changing ttl
|
||||
update_object_value 'dns' 'DOMAIN' "$domain" '$TTL' "$ttl"
|
||||
|
||||
# Update serial
|
||||
update_domain_serial
|
||||
# Updating zone
|
||||
if [[ "$DNS_SYSTEM" =~ named|bind ]]; then
|
||||
rebuild_dns_domain_conf
|
||||
fi
|
||||
|
||||
# Updating dns-cluster queue
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
# Check for first sync
|
||||
dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe)
|
||||
if [ -z "$dlock" ]; then
|
||||
cmd="$BIN/v-change-remote-dns-domain-ttl $user $domain $ttl"
|
||||
echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Restarting named
|
||||
$BIN/v-restart-dns "$restart"
|
||||
check_result $? "DNS restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "DNS" "TTL for DNS domain changed (TTL: $ttl, Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,168 @@
|
||||
#!/bin/bash
|
||||
# info: change dns domain record
|
||||
# options: USER DOMAIN ID RECORD TYPE VALUE [PRIORITY] [RESTART] [TTL]
|
||||
#
|
||||
# example: v-change-dns-record admin domain.ua 42 192.18.22.43
|
||||
#
|
||||
# This function for changing DNS record.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
id=$3
|
||||
record=$4
|
||||
rtype=$5
|
||||
dvalue=$6
|
||||
priority=$7
|
||||
restart=$8
|
||||
ttl=$9
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/rebuild.sh
|
||||
source $HESTIA/func/rebuild.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '6' "$#" 'USER DOMAIN ID RECORD TYPE VALUE [PRIORITY] [RESTART] [TTL]'
|
||||
is_format_valid 'user' 'domain' 'id' 'record'
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'dns' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'dns' 'DOMAIN' "$domain"
|
||||
is_object_valid "dns/$domain" 'ID' "$id"
|
||||
is_format_valid 'ttl'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ "$record" = "@" ] && [ "$rtype" = "CNAME" ]; then
|
||||
check_result $E_INVALID "CNAME on root is not allowed"
|
||||
fi
|
||||
|
||||
# Make sure the variable for the optional parameter TTL is empty before parsing
|
||||
# We depend on that later on
|
||||
unset TTL
|
||||
|
||||
# Parsing domain config
|
||||
line=$(grep "ID='$id'" $USER_DATA/dns/$domain.conf)
|
||||
parse_object_kv_list "$line"
|
||||
|
||||
if [ -z "$rtype" ]; then
|
||||
rtype=$TYPE
|
||||
fi
|
||||
|
||||
if [ -z "$priority" ]; then
|
||||
priority=$PRIORITY
|
||||
fi
|
||||
|
||||
# Null priority for none MX/SRV records
|
||||
if [ "$rtype" != 'MX' ] && [ "$rtype" != 'SRV' ]; then
|
||||
priority=''
|
||||
fi
|
||||
|
||||
# Add trailing dot at the end of NS/CNAME/MX/PTR/SRV record
|
||||
if [[ $rtype =~ ^NS|CNAME|MX|PTR|SRV ]]; then
|
||||
trailing_dot=$(echo "$dvalue" | grep "\.$")
|
||||
if [ -z "$trailing_dot" ]; then
|
||||
dvalue="$dvalue."
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $rtype =~ NS|CNAME|MX|PTR|SRV ]]; then
|
||||
dvalue=$(idn2 --quiet "$dvalue")
|
||||
record=$(idn2 --quiet "$record")
|
||||
fi
|
||||
|
||||
if [ "$rtype" != "CAA" ]; then
|
||||
dvalue=${dvalue//\"/}
|
||||
|
||||
if [ "$rtype" != 'SRV' ] && [[ "$dvalue" =~ [\;[:space:]] ]]; then
|
||||
dvalue='"'"$dvalue"'"'
|
||||
fi
|
||||
fi
|
||||
|
||||
#RTYPE wasn't checked make sure to do it now correctly
|
||||
is_format_valid 'user' 'domain' 'id' 'record' 'rtype' 'dvalue'
|
||||
|
||||
# Additional verifications
|
||||
is_dns_fqnd "$TYPE" "$dvalue"
|
||||
is_dns_nameserver_valid "$domain" "$TYPE" "$dvalue"
|
||||
|
||||
if [[ "$RECORD" == "$record" ]] && [[ "$TYPE" == "$rtype" ]] && [[ "$PRIORITY" -eq "$priority" ]] \
|
||||
&& [[ "$VALUE" == "$dvalue" ]] && [[ "$SUSPENDED" == 'no' ]] && [[ "$TTL" -eq "$ttl" ]]; then
|
||||
echo "No pending changes in DNS entry."
|
||||
exit "$E_EXISTS"
|
||||
fi
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Adding record
|
||||
dns_rec="ID='$id' RECORD='$record' TYPE='$rtype' PRIORITY='$priority'"
|
||||
dns_rec="$dns_rec VALUE='$dvalue' SUSPENDED='no' TIME='$time' DATE='$date'"
|
||||
[ -n "$ttl" ] && dns_rec="$dns_rec TTL='$ttl'"
|
||||
# Deleting old record
|
||||
sed -i "/^ID='$id'/d" $USER_DATA/dns/$domain.conf
|
||||
# Add new entry
|
||||
echo "$dns_rec" >> $USER_DATA/dns/$domain.conf
|
||||
|
||||
# Sorting records
|
||||
sort_dns_records
|
||||
|
||||
# Update serial
|
||||
update_domain_serial
|
||||
# Updating zone
|
||||
if [[ "$DNS_SYSTEM" =~ named|bind ]]; then
|
||||
rebuild_dns_domain_conf
|
||||
fi
|
||||
|
||||
# Updating dns-cluster queue
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
# Check for first sync
|
||||
dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe)
|
||||
if [ -z "$dlock" ]; then
|
||||
cmd="$BIN/v-add-remote-dns-domain $user $domain records"
|
||||
echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Restarting named
|
||||
$BIN/v-restart-dns "$restart"
|
||||
check_result $? "DNS restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "DNS" "DNS record value changed (Type: $rtype, Record: $record, Value: $dvalue, Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,93 @@
|
||||
#!/bin/bash
|
||||
# info: change dns domain record id
|
||||
# options: USER DOMAIN ID NEWID [RESTART]
|
||||
#
|
||||
# example: v-change-dns-record-id admin acme.com 24 42 yes
|
||||
#
|
||||
# This function for changing internal record id.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
id=$3
|
||||
newid=$4
|
||||
restart=$5
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/rebuild.sh
|
||||
source $HESTIA/func/rebuild.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '4' "$#" 'USER DOMAIN ID NEWID [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'id' 'newid'
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'dns' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'dns' 'DOMAIN' "$domain"
|
||||
is_object_valid "dns/$domain" 'ID' "$id"
|
||||
is_object_new "dns/$domain" 'ID' "$newid"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Change id
|
||||
sed -i "s/^ID='$id'/ID='$newid'/" $USER_DATA/dns/$domain.conf
|
||||
|
||||
# Sorting records
|
||||
sort_dns_records
|
||||
|
||||
# Update serial
|
||||
update_domain_serial
|
||||
# Updating zone
|
||||
if [[ "$DNS_SYSTEM" =~ named|bind ]]; then
|
||||
rebuild_dns_domain_conf
|
||||
fi
|
||||
|
||||
# Updating dns-cluster queue
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
# Check for first sync
|
||||
dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe)
|
||||
if [ -z "$dlock" ]; then
|
||||
cmd="$BIN/v-add-remote-dns-domain $user $domain records"
|
||||
echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Restarting named
|
||||
$BIN/v-restart-dns "$restart"
|
||||
check_result $? "DNS restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
@ -0,0 +1,317 @@
|
||||
#!/bin/bash
|
||||
# info: change domain owner
|
||||
# options: DOMAIN USER
|
||||
#
|
||||
# example: v-change-domain-owner www.example.com bob
|
||||
#
|
||||
# This function of changing domain ownership.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
domain=$1
|
||||
user=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'DOMAIN USER'
|
||||
is_format_valid 'domain' 'user'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
owner=$($BIN/v-search-domain-owner "$domain")
|
||||
if [ -z "$owner" ]; then
|
||||
check_result "$E_NOTEXIST" "domain $domain doesn't exist"
|
||||
fi
|
||||
if [ "$owner" = "$user" ]; then
|
||||
echo "ERROR: $domain is already owned by $user."
|
||||
exit
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
echo "Moving $domain from $owner to $user, please wait..."
|
||||
|
||||
# WEB domain
|
||||
web_data=$(grep "DOMAIN='$domain'" $HESTIA/data/users/$owner/web.conf)
|
||||
if [ -n "$web_data" ]; then
|
||||
echo "[*] Moving web domain..."
|
||||
$BIN/v-suspend-web-domain "$owner" "$domain" >> /dev/null 2>&1
|
||||
parse_object_kv_list "$web_data"
|
||||
|
||||
if [ -n "$CUSTOM_DOCROOT" ]; then
|
||||
if [ -z $(echo $CUSTOM_DOCROOT | grep -i "/home/$owner/web/$domain") ]; then
|
||||
docdomain=$(echo "$CUSTOM_DOCROOT" | cut -d'/' -f5)
|
||||
$BIN/v-list-web-domain $user $docdomain > /dev/null
|
||||
if [ "$?" != 0 ]; then
|
||||
echo "Error: Target domain doesn't belong to the new user"
|
||||
exit $E_NOTEXIST
|
||||
fi
|
||||
new_docroot=$(echo $CUSTOM_DOCROOT | sed "s/\/home\/$owner/\/home\/$user/")
|
||||
new_php_docroot=$(echo $CUSTOM_PHPROOT | sed "s/\/home\/$owner/\/home\/$user/")
|
||||
|
||||
else
|
||||
new_docroot=$(echo $CUSTOM_DOCROOT | sed "s/\/home\/$owner/\/home\/$user/")
|
||||
new_php_docroot=$(echo $CUSTOM_PHPROOT | sed "s/\/home\/$owner/\/home\/$user/")
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$(echo $(get_user_ips) | grep $IP)" ]; then
|
||||
echo "[*] IP dedicated to $owner select new ip address..."
|
||||
get_user_ip
|
||||
fi
|
||||
old_ip=$IP
|
||||
new_ip=$ip
|
||||
echo $ip
|
||||
|
||||
# Change IP
|
||||
if [ -n "$ip" ]; then
|
||||
web_data=$(echo "$web_data" | sed "s/IP='$IP'/IP='$ip'/")
|
||||
fi
|
||||
if [ -n "$new_docroot" ]; then
|
||||
web_data=$(echo "$web_data" | sed "s|CUSTOM_DOCROOT='$CUSTOM_DOCROOT'|CUSTOM_DOCROOT='$new_docroot'|")
|
||||
web_data=$(echo "$web_data" | sed "s|CUSTOM_PHPROOT='$CUSTOM_PHPROOT'|CUSTOM_PHPROOT='$new_php_docroot'|")
|
||||
fi
|
||||
web_data=$(echo "$web_data" | sed "s/SUSPENDED='no'/SUSPENDED='yes'/")
|
||||
|
||||
# Check SSL
|
||||
if [ "$SSL" = 'yes' ]; then
|
||||
ssl_crt=$HESTIA/data/users/$owner/ssl/$domain.crt
|
||||
ssl_key=$HESTIA/data/users/$owner/ssl/$domain.key
|
||||
ssl_ca=$HESTIA/data/users/$owner/ssl/$domain.ca
|
||||
ssl_pem=$HESTIA/data/users/$owner/ssl/$domain.pem
|
||||
mv $ssl_crt $HESTIA/data/users/$user/ssl/
|
||||
mv $ssl_key $HESTIA/data/users/$user/ssl/
|
||||
mv $ssl_ca $HESTIA/data/users/$user/ssl/ >> /dev/null 2>&1
|
||||
mv $ssl_pem $HESTIA/data/users/$user/ssl/ >> /dev/null 2>&1
|
||||
rm -f $HOMEDIR/$owner/conf/web/ssl.$domain.*
|
||||
fi
|
||||
|
||||
# Check ftp user account
|
||||
if [ -n "$FTP_USER" ]; then
|
||||
/usr/sbin/userdel -f "$FTP_USER" >> /dev/null 2>&1
|
||||
old_str="FTP_USER='$FTP_USER'"
|
||||
new_str=$(echo "$old_str" | sed "s/${owner}_/${user}_/")
|
||||
web_data=$(echo "$web_data" | sed "s/$old_str/$new_str/")
|
||||
fi
|
||||
|
||||
# Move config
|
||||
sed -i "/DOMAIN='$domain'/d" $HESTIA/data/users/$owner/web.conf
|
||||
echo "$web_data" >> $HESTIA/data/users/$user/web.conf
|
||||
|
||||
# Move data
|
||||
mv $HOMEDIR/$owner/web/$domain $HOMEDIR/$user/web/
|
||||
|
||||
# Change ownership
|
||||
find "$HOMEDIR/$user/web/$domain" -user "$owner" \
|
||||
-exec chown -h $user:$user {} \;
|
||||
|
||||
# Rebuild config
|
||||
$BIN/v-unsuspend-web-domain "$user" "$domain" no >> /dev/null 2>&1
|
||||
$BIN/v-rebuild-web-domains "$owner" no
|
||||
$BIN/v-rebuild-web-domains "$user"
|
||||
|
||||
# Cleanup old config
|
||||
rm -rf "$HOMEDIR/$owner/conf/web/$domain/"
|
||||
fi
|
||||
|
||||
# DNS domain
|
||||
dns_data=$(grep "DOMAIN='$domain'" $HESTIA/data/users/$owner/dns.conf)
|
||||
if [ -n "$dns_data" ]; then
|
||||
echo "[*] Moving DNS zone and records..."
|
||||
parse_object_kv_list "$dns_data"
|
||||
|
||||
# Change IP
|
||||
if [ -n "$ip" ]; then
|
||||
dns_data=$(echo "$dns_data" | sed "s/IP='$IP'/IP='$ip'/")
|
||||
sed -i "s/$IP/$ip/g" $HESTIA/data/users/$owner/dns/$domain.conf
|
||||
fi
|
||||
|
||||
# Move config
|
||||
sed -i "/DOMAIN='$domain'/d" $HESTIA/data/users/$owner/dns.conf
|
||||
echo "$dns_data" >> $HESTIA/data/users/$user/dns.conf
|
||||
|
||||
# Move dns records
|
||||
mv $HESTIA/data/users/$owner/dns/$domain.conf \
|
||||
$HESTIA/data/users/$user/dns/
|
||||
|
||||
# Rebuild config
|
||||
$BIN/v-unsuspend-dns-domain "$user" "$domain" no >> /dev/null 2>&1
|
||||
$BIN/v-rebuild-dns-domains "$owner" no
|
||||
$BIN/v-rebuild-dns-domains "$user"
|
||||
|
||||
# Cleanup old config
|
||||
rm -f $HOMEDIR/$owner/conf/dns/$domain.db
|
||||
|
||||
# Resync dns cluster
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
$BIN/v-sync-dns-cluster
|
||||
fi
|
||||
fi
|
||||
|
||||
# MAIL domain
|
||||
mail_data=$(grep "DOMAIN='$domain'" $HESTIA/data/users/$owner/mail.conf)
|
||||
if [ -n "$mail_data" ]; then
|
||||
$BIN/v-suspend-mail-domain "$owner" "$domain" >> /dev/null 2>&1
|
||||
echo "[*] Moving mail domain and accounts..."
|
||||
|
||||
parse_object_kv_list "$mail_data"
|
||||
|
||||
# Ensure mail configuration directory exists for receiving user
|
||||
if [ ! -e "$HOMEDIR/$user/conf/mail/$domain/" ]; then
|
||||
mkdir -p $HOMEDIR/$user/conf/mail/$domain/
|
||||
fi
|
||||
|
||||
# Move config
|
||||
sed -i "/DOMAIN='$domain'/d" $HESTIA/data/users/$owner/mail.conf
|
||||
mail_data=$(echo "$mail_data" | sed "s/SUSPENDED='no'/SUSPENDED='yes'/")
|
||||
echo "$mail_data" >> $HESTIA/data/users/$user/mail.conf
|
||||
mv -f $HESTIA/data/users/$owner/mail/$domain.conf \
|
||||
$HESTIA/data/users/$user/mail/
|
||||
|
||||
# Move DKIM
|
||||
if [ -e "$HESTIA/data/users/$owner/mail/$domain.pem" ]; then
|
||||
mv -f $HESTIA/data/users/$owner/mail/$domain.pem \
|
||||
$HESTIA/data/users/$user/mail/
|
||||
mv -f $HESTIA/data/users/$owner/mail/$domain.pub \
|
||||
$HESTIA/data/users/$user/mail/
|
||||
fi
|
||||
|
||||
# Move SSL certificates
|
||||
if [ "$SSL" = 'yes' ]; then
|
||||
# Ensure that SSL directory exists and move certificates
|
||||
mkdir -p $HESTIA/data/users/$user/ssl/
|
||||
mkdir -p $HOMEDIR/$user/conf/mail/$domain/ssl/
|
||||
|
||||
ssl_crt=$HESTIA/data/users/$owner/ssl/mail.$domain.crt
|
||||
ssl_key=$HESTIA/data/users/$owner/ssl/mail.$domain.key
|
||||
ssl_ca=$HESTIA/data/users/$owner/ssl/mail.$domain.ca
|
||||
ssl_pem=$HESTIA/data/users/$owner/ssl/mail.$domain.pem
|
||||
mv $ssl_crt $HESTIA/data/users/$user/ssl/
|
||||
mv $ssl_key $HESTIA/data/users/$user/ssl/
|
||||
mv $ssl_ca $HESTIA/data/users/$user/ssl/ >> /dev/null 2>&1
|
||||
mv $ssl_pem $HESTIA/data/users/$user/ssl/ >> /dev/null 2>&1
|
||||
|
||||
# Add certificate to user home directory
|
||||
cp -f $HESTIA/data/users/$user/ssl/mail.$domain.crt $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.crt
|
||||
cp -f $HESTIA/data/users/$user/ssl/mail.$domain.key $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.key
|
||||
cp -f $HESTIA/data/users/$user/ssl/mail.$domain.pem $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.pem
|
||||
if [ -e "$HESTIA/data/users/$user/ssl/mail.$domain.ca" ]; then
|
||||
cp -f $HESTIA/data/users/$user/ssl/mail.$domain.ca $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.ca
|
||||
fi
|
||||
|
||||
# Add domain SSL configuration to dovecot
|
||||
if [ -f "/etc/dovecot/conf.d/domains/$domain.conf" ]; then
|
||||
rm -f /etc/dovecot/conf.d/domains/$domain.conf
|
||||
fi
|
||||
|
||||
echo "" >> /etc/dovecot/conf.d/domains/$domain.conf
|
||||
echo "local_name mail.$domain {" >> /etc/dovecot/conf.d/domains/$domain.conf
|
||||
echo " ssl_cert = <$HOMEDIR/$user/conf/mail/$domain/ssl/$domain.pem" >> /etc/dovecot/conf.d/domains/$domain.conf
|
||||
echo " ssl_key = <$HOMEDIR/$user/conf/mail/$domain/ssl/$domain.key" >> /etc/dovecot/conf.d/domains/$domain.conf
|
||||
echo "}" >> /etc/dovecot/conf.d/domains/$domain.conf
|
||||
|
||||
# Add domain SSL configuration to exim4
|
||||
# Cleanup symlinks
|
||||
find /usr/local/hestia/ssl/mail -xtype l -delete
|
||||
|
||||
ln -s -f $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.pem /usr/local/hestia/ssl/mail/mail.$domain.crt
|
||||
ln -s -f $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.key /usr/local/hestia/ssl/mail/mail.$domain.key
|
||||
|
||||
# Set correct permissions on certificates
|
||||
chmod 750 $HOMEDIR/$user/conf/mail/$domain/ssl
|
||||
chown -R $MAIL_USER:mail $HOMEDIR/$user/conf/mail/$domain/ssl
|
||||
chmod 0644 $HOMEDIR/$user/conf/mail/$domain/ssl/*
|
||||
chown -h $user:mail $HOMEDIR/$user/conf/mail/$domain/ssl/*
|
||||
chmod -R 0644 /usr/local/hestia/ssl/mail/*
|
||||
chown -h $user:mail /usr/local/hestia/ssl/mail/*
|
||||
fi
|
||||
|
||||
# Move data
|
||||
mv $HOMEDIR/$owner/mail/$domain $HOMEDIR/$user/mail/
|
||||
|
||||
# Change ownership
|
||||
find $HOMEDIR/$user/mail/$domain -user $owner \
|
||||
-exec chown -h $user {} \;
|
||||
|
||||
# Checking exim username for later chowning
|
||||
exim_user="exim"
|
||||
check_exim_username=$(grep -c '^Debian-exim:' /etc/passwd)
|
||||
if [ "$check_exim_username" -eq 1 ]; then
|
||||
exim_user="Debian-exim"
|
||||
fi
|
||||
# Chowning mail conf files to exim user
|
||||
if [ -d "$HOMEDIR/$user/conf/mail/$domain" ]; then
|
||||
find $HOMEDIR/$user/conf/mail/$domain -user root \
|
||||
-exec chown $exim_user {} \;
|
||||
fi
|
||||
|
||||
# Remove old mail directory from original owner
|
||||
if [ -e "$HOMEDIR/$owner/mail/$domain" ]; then
|
||||
rm -rf "$HOMEDIR/$owner/mail/$domain"
|
||||
fi
|
||||
|
||||
# Remove old mail configuration directory from original owner
|
||||
if [ -e "$HOMEDIR/$owner/conf/mail/$domain" ]; then
|
||||
rm -rf "$HOMEDIR/$owner/conf/mail/$domain"
|
||||
fi
|
||||
if [ -e "$HESTIA/data/users/$owner/mail/$domain.conf" ]; then
|
||||
rm -f "$HESTIA/data/users/$owner/mail/$domain.conf"
|
||||
fi
|
||||
|
||||
# Rebuild config
|
||||
$BIN/v-unsuspend-mail-domain "$user" "$domain" no
|
||||
$BIN/v-rebuild-mail-domains "$owner" no
|
||||
$BIN/v-rebuild-mail-domains "$user"
|
||||
fi
|
||||
|
||||
# Update counters
|
||||
$BIN/v-update-user-counters "$owner"
|
||||
$BIN/v-update-user-counters "$user"
|
||||
|
||||
# Mail domains currently don't have the IP variable set see #2306
|
||||
if [ -n "$old_ip" ]; then
|
||||
# Recalculate ip usage
|
||||
if [ -n "$ip" ]; then
|
||||
decrease_ip_value $old_ip $owner
|
||||
increase_ip_value $new_ip
|
||||
else
|
||||
# recalculate ip
|
||||
decrease_ip_value $old_ip $owner
|
||||
increase_ip_value $old_ip
|
||||
fi
|
||||
fi
|
||||
# Send notification to panel
|
||||
if [ -n "$web_data" ] || [ -n "$dns_data" ] || [ -n "$mail_data" ]; then
|
||||
$BIN/v-add-user-notification "$user" "$domain has been added to your account" ''
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "System" "Domain moved between users (Domain: $domain, Old user: $owner, New User: $user)."
|
||||
$BIN/v-log-action "$user" "Info" "System" "New domain added to account (Domain: $domain)."
|
||||
$BIN/v-log-action "$owner" "Info" "System" "Domain removed from account (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue